diff options
263 files changed, 3832 insertions, 2323 deletions
diff --git a/api/current.txt b/api/current.txt index 6023aabc1ca3..ac97b543fbdb 100644 --- a/api/current.txt +++ b/api/current.txt @@ -26513,7 +26513,6 @@ package android.net.wifi { method public boolean isTdlsSupported(); method public boolean isWifiEnabled(); method public deprecated boolean pingSupplicant(); - method public void queryPasspointIcon(long, java.lang.String); method public boolean reassociate(); method public boolean reconnect(); method public boolean removeNetwork(int); @@ -26526,29 +26525,17 @@ package android.net.wifi { method public boolean startScan(); method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback); method public int updateNetwork(android.net.wifi.WifiConfiguration); - field public static final java.lang.String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; - field public static final java.lang.String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; - field public static final java.lang.String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; - field public static final java.lang.String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; field public static final int ERROR_AUTHENTICATING = 1; // 0x1 - field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA"; field public static final java.lang.String EXTRA_BSSID = "bssid"; - field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; - field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; - field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS"; - field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; - field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON"; field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo"; field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi"; field public static final java.lang.String EXTRA_NEW_STATE = "newState"; field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated"; - field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected"; field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError"; - field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL"; field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo"; field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state"; field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; @@ -33907,7 +33894,6 @@ package android.provider { field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_CHAT_ID = "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID"; field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_NAME = "android.provider.extra.RECIPIENT_CONTACT_NAME"; field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_URI = "android.provider.extra.RECIPIENT_CONTACT_URI"; - field public static final java.lang.String EXTRA_SENDER_ACCOUNT_HASH = "android.provider.extra.SENDER_ACCOUNT_HASH"; field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT"; field public static final java.lang.String METADATA_ACCOUNT_TYPE = "android.provider.account_type"; field public static final java.lang.String METADATA_MIMETYPE = "android.provider.mimetype"; diff --git a/api/system-current.txt b/api/system-current.txt index 67b6e821a589..a2c2771b4844 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -29038,7 +29038,6 @@ package android.net.wifi { method public boolean isWifiEnabled(); method public boolean isWifiScannerSupported(); method public deprecated boolean pingSupplicant(); - method public void queryPasspointIcon(long, java.lang.String); method public boolean reassociate(); method public boolean reconnect(); method public boolean removeNetwork(int); @@ -29055,10 +29054,6 @@ package android.net.wifi { method public boolean startScan(android.os.WorkSource); method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback); method public int updateNetwork(android.net.wifi.WifiConfiguration); - field public static final java.lang.String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; - field public static final java.lang.String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; - field public static final java.lang.String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; - field public static final java.lang.String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; field public static final int CHANGE_REASON_ADDED = 0; // 0x0 @@ -29066,14 +29061,8 @@ package android.net.wifi { field public static final int CHANGE_REASON_REMOVED = 1; // 0x1 field public static final java.lang.String CONFIGURED_NETWORKS_CHANGED_ACTION = "android.net.wifi.CONFIGURED_NETWORKS_CHANGE"; field public static final int ERROR_AUTHENTICATING = 1; // 0x1 - field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA"; field public static final java.lang.String EXTRA_BSSID = "bssid"; - field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; field public static final java.lang.String EXTRA_CHANGE_REASON = "changeReason"; - field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; - field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS"; - field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; - field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON"; field public static final java.lang.String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges"; field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo"; field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi"; @@ -29081,10 +29070,8 @@ package android.net.wifi { field public static final java.lang.String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated"; - field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected"; field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError"; - field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL"; field public static final java.lang.String EXTRA_WIFI_AP_STATE = "wifi_state"; field public static final java.lang.String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et"; @@ -36821,7 +36808,6 @@ package android.provider { field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_CHAT_ID = "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID"; field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_NAME = "android.provider.extra.RECIPIENT_CONTACT_NAME"; field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_URI = "android.provider.extra.RECIPIENT_CONTACT_URI"; - field public static final java.lang.String EXTRA_SENDER_ACCOUNT_HASH = "android.provider.extra.SENDER_ACCOUNT_HASH"; field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT"; field public static final java.lang.String METADATA_ACCOUNT_TYPE = "android.provider.account_type"; field public static final java.lang.String METADATA_MIMETYPE = "android.provider.mimetype"; diff --git a/api/test-current.txt b/api/test-current.txt index cf119d112010..1cad48ead7de 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -26622,7 +26622,6 @@ package android.net.wifi { method public boolean isTdlsSupported(); method public boolean isWifiEnabled(); method public deprecated boolean pingSupplicant(); - method public void queryPasspointIcon(long, java.lang.String); method public boolean reassociate(); method public boolean reconnect(); method public boolean removeNetwork(int); @@ -26635,29 +26634,17 @@ package android.net.wifi { method public boolean startScan(); method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback); method public int updateNetwork(android.net.wifi.WifiConfiguration); - field public static final java.lang.String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; - field public static final java.lang.String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; - field public static final java.lang.String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; - field public static final java.lang.String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; field public static final int ERROR_AUTHENTICATING = 1; // 0x1 - field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA"; field public static final java.lang.String EXTRA_BSSID = "bssid"; - field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; - field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; - field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS"; - field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; - field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON"; field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo"; field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi"; field public static final java.lang.String EXTRA_NEW_STATE = "newState"; field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated"; - field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected"; field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError"; - field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL"; field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo"; field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state"; field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; @@ -34044,7 +34031,6 @@ package android.provider { field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_CHAT_ID = "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID"; field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_NAME = "android.provider.extra.RECIPIENT_CONTACT_NAME"; field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_URI = "android.provider.extra.RECIPIENT_CONTACT_URI"; - field public static final java.lang.String EXTRA_SENDER_ACCOUNT_HASH = "android.provider.extra.SENDER_ACCOUNT_HASH"; field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT"; field public static final java.lang.String METADATA_ACCOUNT_TYPE = "android.provider.account_type"; field public static final java.lang.String METADATA_MIMETYPE = "android.provider.mimetype"; diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index b60aed68ba1c..d71573f7ca50 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -63,6 +63,7 @@ import android.os.ShellCallback; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.os.storage.StorageManager; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; @@ -1471,7 +1472,8 @@ public final class Pm { } ClearDataObserver obs = new ClearDataObserver(); try { - mPm.freeStorageAndNotify(volumeUuid, sizeVal, obs); + mPm.freeStorageAndNotify(volumeUuid, sizeVal, + StorageManager.FLAG_ALLOCATE_DEFY_RESERVED, obs); synchronized (obs) { while (!obs.finished) { try { diff --git a/core/java/android/animation/AnimationHandler.java b/core/java/android/animation/AnimationHandler.java index e2e5a8f66288..260323fe2d10 100644 --- a/core/java/android/animation/AnimationHandler.java +++ b/core/java/android/animation/AnimationHandler.java @@ -136,7 +136,8 @@ public class AnimationHandler { private void doAnimationFrame(long frameTime) { long currentTime = SystemClock.uptimeMillis(); - for (int i = 0; i < mAnimationCallbacks.size(); i++) { + final int size = mAnimationCallbacks.size(); + for (int i = 0; i < size; i++) { final AnimationFrameCallback callback = mAnimationCallbacks.get(i); if (callback == null) { continue; diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index 4e31e44d6e75..e686a89accef 100644 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -1397,7 +1397,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio if (mStartTime < 0) { // First frame. If there is start delay, start delay count down will happen *after* this // frame. - mStartTime = mReversing ? frameTime : frameTime + mStartDelay; + mStartTime = mReversing ? frameTime : frameTime + (long) (mStartDelay * sDurationScale); } // Handle pause/resume diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index b439c1dc02c4..b360c82374d0 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6142,6 +6142,7 @@ public class Activity extends ContextThemeWrapper * * @param action the action to run on the UI thread */ + @Override public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 09252175a1db..7e230a3d9ea4 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1139,8 +1139,12 @@ public class ActivityManager { * E.g. freeform, split-screen, picture-in-picture. * @hide */ - static public boolean supportsMultiWindow() { - return !isLowRamDeviceStatic() + static public boolean supportsMultiWindow(Context context) { + // On watches, multi-window is used to present essential system UI, and thus it must be + // supported regardless of device memory characteristics. + boolean isWatch = context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_WATCH); + return (!isLowRamDeviceStatic() || isWatch) && Resources.getSystem().getBoolean( com.android.internal.R.bool.config_supportsMultiWindow); } @@ -1149,8 +1153,8 @@ public class ActivityManager { * Returns true if the system supports split screen multi-window. * @hide */ - static public boolean supportsSplitScreenMultiWindow() { - return supportsMultiWindow() + static public boolean supportsSplitScreenMultiWindow(Context context) { + return supportsMultiWindow(context) && Resources.getSystem().getBoolean( com.android.internal.R.bool.config_supportsSplitScreenMultiWindow); } diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 53608fbdd4bb..c4d51168d20c 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -25,6 +25,8 @@ import android.annotation.TestApi; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.GraphicBuffer; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; @@ -826,7 +828,11 @@ public class ActivityOptions { case ANIM_THUMBNAIL_SCALE_DOWN: case ANIM_THUMBNAIL_ASPECT_SCALE_UP: case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: - mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL); + // Unpackage the GraphicBuffer from the parceled thumbnail + final GraphicBuffer buffer = opts.getParcelable(KEY_ANIM_THUMBNAIL); + if (buffer != null) { + mThumbnail = Bitmap.createHardwareBitmap(buffer); + } mStartX = opts.getInt(KEY_ANIM_START_X, 0); mStartY = opts.getInt(KEY_ANIM_START_Y, 0); mWidth = opts.getInt(KEY_ANIM_WIDTH, 0); @@ -919,9 +925,14 @@ public class ActivityOptions { return mCustomInPlaceResId; } - /** @hide */ - public Bitmap getThumbnail() { - return mThumbnail; + /** + * The thumbnail is copied into a hardware bitmap when it is bundled and sent to the system, so + * it should always be backed by a GraphicBuffer on the other end. + * + * @hide + */ + public GraphicBuffer getThumbnail() { + return mThumbnail.createGraphicBufferHandle(); } /** @hide */ @@ -1230,7 +1241,14 @@ public class ActivityOptions { case ANIM_THUMBNAIL_SCALE_DOWN: case ANIM_THUMBNAIL_ASPECT_SCALE_UP: case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN: - b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail); + // Once we parcel the thumbnail for transfering over to the system, create a copy of + // the bitmap to a hardware bitmap and pass through the GraphicBuffer + if (mThumbnail == null) { + b.putParcelable(KEY_ANIM_THUMBNAIL, null); + } else { + final Bitmap hwBitmap = mThumbnail.copy(Config.HARDWARE, true /* immutable */); + b.putParcelable(KEY_ANIM_THUMBNAIL, hwBitmap.createGraphicBufferHandle()); + } b.putInt(KEY_ANIM_START_X, mStartX); b.putInt(KEY_ANIM_START_Y, mStartY); b.putInt(KEY_ANIM_WIDTH, mWidth); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 525b15113855..e5c420876c8a 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -2108,7 +2108,7 @@ public class ApplicationPackageManager extends PackageManager { public void freeStorageAndNotify(String volumeUuid, long idealStorageSize, IPackageDataObserver observer) { try { - mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, observer); + mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, 0, observer); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2117,7 +2117,7 @@ public class ApplicationPackageManager extends PackageManager { @Override public void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) { try { - mPM.freeStorage(volumeUuid, freeStorageSize, pi); + mPM.freeStorage(volumeUuid, freeStorageSize, 0, pi); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 3ed174b2d46f..31f52dbea548 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1168,7 +1168,7 @@ public class Notification implements Parcelable */ public static final int GROUP_ALERT_CHILDREN = 2; - private int mGroupAlertBehavior = GROUP_ALERT_ALL; + private int mGroupAlertBehavior = GROUP_ALERT_CHILDREN; /** * If this notification is being shown as a badge, always show as a number. @@ -2640,6 +2640,20 @@ public class Notification implements Parcelable } /** + * @hide + */ + public boolean suppressAlertingDueToGrouping() { + if (isGroupSummary() + && getGroupAlertBehavior() == Notification.GROUP_ALERT_CHILDREN) { + return true; + } else if (isGroupChild() + && getGroupAlertBehavior() == Notification.GROUP_ALERT_SUMMARY) { + return true; + } + return false; + } + + /** * Builder class for {@link Notification} objects. * * Provides a convenient way to set the various fields of a {@link Notification} and generate diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java index 8a4f8a626c71..0f006b6618b3 100644 --- a/core/java/android/app/TimePickerDialog.java +++ b/core/java/android/app/TimePickerDialog.java @@ -151,10 +151,7 @@ public class TimePickerDialog extends AlertDialog implements OnClickListener, @Override public void onClick(View view) { if (mTimePicker.validateInput()) { - if (mTimeSetListener != null) { - mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(), - mTimePicker.getCurrentMinute()); - } + TimePickerDialog.this.onClick(TimePickerDialog.this, BUTTON_POSITIVE); dismiss(); } } diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index 3cb59f27bfaf..87e516cabba5 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -35,6 +35,7 @@ import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; import java.util.Objects; /** @@ -501,7 +502,7 @@ public class JobInfo implements Parcelable { if (constraintFlags != j.constraintFlags) { return false; } - if (!Objects.deepEquals(triggerContentUris, j.triggerContentUris)) { + if (!Arrays.equals(triggerContentUris, j.triggerContentUris)) { return false; } if (triggerContentUpdateDelay != j.triggerContentUpdateDelay) { @@ -556,37 +557,37 @@ public class JobInfo implements Parcelable { public int hashCode() { int hashCode = jobId; if (extras != null) { - hashCode = 31*hashCode + extras.hashCode(); + hashCode = 31 * hashCode + extras.hashCode(); } if (transientExtras != null) { - hashCode = 31*hashCode + transientExtras.hashCode(); + hashCode = 31 * hashCode + transientExtras.hashCode(); } if (clipData != null) { - hashCode = 31*hashCode + clipData.hashCode(); + hashCode = 31 * hashCode + clipData.hashCode(); } hashCode = 31*hashCode + clipGrantFlags; if (service != null) { - hashCode = 31*hashCode + service.hashCode(); + hashCode = 31 * hashCode + service.hashCode(); } - hashCode = 31*hashCode + constraintFlags; + hashCode = 31 * hashCode + constraintFlags; if (triggerContentUris != null) { - hashCode = 31*hashCode + triggerContentUris.hashCode(); + hashCode = 31 * hashCode + Arrays.hashCode(triggerContentUris); } - hashCode = 31*hashCode + Long.hashCode(triggerContentUpdateDelay); - hashCode = 31*hashCode + Long.hashCode(triggerContentMaxDelay); - hashCode = 31*hashCode + Boolean.hashCode(hasEarlyConstraint); - hashCode = 31*hashCode + Boolean.hashCode(hasLateConstraint); - hashCode = 31*hashCode + networkType; - hashCode = 31*hashCode + Long.hashCode(minLatencyMillis); - hashCode = 31*hashCode + Long.hashCode(maxExecutionDelayMillis); - hashCode = 31*hashCode + Boolean.hashCode(isPeriodic); - hashCode = 31*hashCode + Boolean.hashCode(isPersisted); - hashCode = 31*hashCode + Long.hashCode(intervalMillis); - hashCode = 31*hashCode + Long.hashCode(flexMillis); - hashCode = 31*hashCode + Long.hashCode(initialBackoffMillis); - hashCode = 31*hashCode + backoffPolicy; - hashCode = 31*hashCode + priority; - hashCode = 31*hashCode + flags; + hashCode = 31 * hashCode + Long.hashCode(triggerContentUpdateDelay); + hashCode = 31 * hashCode + Long.hashCode(triggerContentMaxDelay); + hashCode = 31 * hashCode + Boolean.hashCode(hasEarlyConstraint); + hashCode = 31 * hashCode + Boolean.hashCode(hasLateConstraint); + hashCode = 31 * hashCode + networkType; + hashCode = 31 * hashCode + Long.hashCode(minLatencyMillis); + hashCode = 31 * hashCode + Long.hashCode(maxExecutionDelayMillis); + hashCode = 31 * hashCode + Boolean.hashCode(isPeriodic); + hashCode = 31 * hashCode + Boolean.hashCode(isPersisted); + hashCode = 31 * hashCode + Long.hashCode(intervalMillis); + hashCode = 31 * hashCode + Long.hashCode(flexMillis); + hashCode = 31 * hashCode + Long.hashCode(initialBackoffMillis); + hashCode = 31 * hashCode + backoffPolicy; + hashCode = 31 * hashCode + priority; + hashCode = 31 * hashCode + flags; return hashCode; } diff --git a/core/java/android/app/job/JobServiceEngine.java b/core/java/android/app/job/JobServiceEngine.java index b0ec6502c4b1..ab94da843635 100644 --- a/core/java/android/app/job/JobServiceEngine.java +++ b/core/java/android/app/job/JobServiceEngine.java @@ -210,6 +210,9 @@ public abstract class JobServiceEngine { * information. */ public void jobFinished(JobParameters params, boolean needsReschedule) { + if (params == null) { + throw new NullPointerException("params"); + } Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params); m.arg2 = needsReschedule ? 1 : 0; m.sendToTarget(); diff --git a/core/java/android/app/usage/IStorageStatsManager.aidl b/core/java/android/app/usage/IStorageStatsManager.aidl index 5d1550f1a557..15e5ea5f44ff 100644 --- a/core/java/android/app/usage/IStorageStatsManager.aidl +++ b/core/java/android/app/usage/IStorageStatsManager.aidl @@ -24,6 +24,7 @@ interface IStorageStatsManager { boolean isQuotaSupported(String volumeUuid, String callingPackage); long getTotalBytes(String volumeUuid, String callingPackage); long getFreeBytes(String volumeUuid, String callingPackage); + long getCacheBytes(String volumeUuid, String callingPackage); long getCacheQuotaBytes(String volumeUuid, int uid, String callingPackage); StorageStats queryStatsForPackage(String volumeUuid, String packageName, int userId, String callingPackage); StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage); diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java index d9d958c0653c..0b2b1900c4e0 100644 --- a/core/java/android/app/usage/StorageStatsManager.java +++ b/core/java/android/app/usage/StorageStatsManager.java @@ -142,6 +142,24 @@ public class StorageStatsManager { return getFreeBytes(convert(uuid)); } + /** {@hide} */ + public @BytesLong long getCacheBytes(@NonNull UUID storageUuid) throws IOException { + try { + return mService.getCacheBytes(convert(storageUuid), mContext.getOpPackageName()); + } catch (ParcelableException e) { + e.maybeRethrow(IOException.class); + throw new RuntimeException(e); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** {@hide} */ + @Deprecated + public long getCacheBytes(String uuid) throws IOException { + return getCacheBytes(convert(uuid)); + } + /** * Return storage statistics for a specific package on the requested storage * volume. diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 7aaf453e404d..2ebfa8fb3ac2 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -360,7 +360,7 @@ interface IPackageManager { * the operation is completed */ void freeStorageAndNotify(in String volumeUuid, in long freeStorageSize, - IPackageDataObserver observer); + int storageFlags, IPackageDataObserver observer); /** * Free storage by deleting LRU sorted list of cache files across @@ -384,7 +384,7 @@ interface IPackageManager { * to indicate that no call back is desired. */ void freeStorage(in String volumeUuid, in long freeStorageSize, - in IntentSender pi); + int storageFlags, in IntentSender pi); /** * Delete all the cache files in an applications cache directory diff --git a/core/java/android/nfc/IAppCallback.aidl b/core/java/android/nfc/IAppCallback.aidl index c027d54647bd..133146de2aa1 100644 --- a/core/java/android/nfc/IAppCallback.aidl +++ b/core/java/android/nfc/IAppCallback.aidl @@ -25,6 +25,6 @@ import android.nfc.Tag; interface IAppCallback { BeamShareData createBeamShareData(byte peerLlcpVersion); - void onNdefPushComplete(byte peerLlcpVersion); - void onTagDiscovered(in Tag tag); + oneway void onNdefPushComplete(byte peerLlcpVersion); + oneway void onTagDiscovered(in Tag tag); } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 499d6bbdf535..ecc4dec47af7 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -162,6 +162,11 @@ public abstract class BatteryStats implements Parcelable { public static final int AGGREGATED_WAKE_TYPE_PARTIAL = 20; /** + * A constant indicating a bluetooth scan timer for unoptimized scans. + */ + public static final int BLUETOOTH_UNOPTIMIZED_SCAN_ON = 21; + + /** * Include all of the data in the stats, including previously saved data. */ public static final int STATS_SINCE_CHARGED = 0; @@ -191,8 +196,12 @@ public abstract class BatteryStats implements Parcelable { * New in version 21: * - Actual (not just apportioned) Wakelock time is also recorded. * - Aggregated partial wakelock time (per uid, instead of per wakelock) is recorded. + * - BLE scan result count + * - CPU frequency time per uid + * New in version 22: + * - BLE scan result background count, BLE unoptimized scan time */ - static final String CHECKIN_VERSION = "21"; + static final String CHECKIN_VERSION = "22"; /** * Old version, we hit 9 and ran out of room, need to remove. @@ -217,9 +226,10 @@ public abstract class BatteryStats implements Parcelable { private static final String STATE_TIME_DATA = "st"; // wl line is: // BATTERY_STATS_CHECKIN_VERSION, uid, which, "wl", name, - // full totalTime, 'f', count, current duration, max duration, total duration, - // partial totalTime, 'p', count, current duration, max duration, total duration, - // window totalTime, 'w', count, current duration, max duration, total duration + // full totalTime, 'f', count, current duration, max duration, total duration, + // partial totalTime, 'p', count, current duration, max duration, total duration, + // bg partial totalTime, 'bp', count, current duration, max duration, total duration, + // window totalTime, 'w', count, current duration, max duration, total duration // [Currently, full and window wakelocks have durations current = max = total = -1] private static final String WAKELOCK_DATA = "wl"; // awl line is: @@ -565,7 +575,10 @@ public abstract class BatteryStats implements Parcelable { public abstract Timer getForegroundActivityTimer(); public abstract Timer getBluetoothScanTimer(); public abstract Timer getBluetoothScanBackgroundTimer(); + public abstract Timer getBluetoothUnoptimizedScanTimer(); + public abstract Timer getBluetoothUnoptimizedScanBackgroundTimer(); public abstract Counter getBluetoothScanResultCounter(); + public abstract Counter getBluetoothScanResultBgCounter(); public abstract long[] getCpuFreqTimes(int which); public abstract long[] getScreenOffCpuFreqTimes(int which); @@ -3429,10 +3442,29 @@ public abstract class BatteryStats implements Parcelable { final long actualTime = bleTimer.getTotalDurationMsLocked(rawRealtimeMs); final long actualTimeBg = bleTimerBg != null ? bleTimerBg.getTotalDurationMsLocked(rawRealtimeMs) : 0; + // Result counters final int resultCount = u.getBluetoothScanResultCounter() != null ? u.getBluetoothScanResultCounter().getCountLocked(which) : 0; + final int resultCountBg = u.getBluetoothScanResultBgCounter() != null ? + u.getBluetoothScanResultBgCounter().getCountLocked(which) : 0; + // Unoptimized scan timer. Unpooled and since reset (regardless of 'which'). + final Timer unoptimizedScanTimer = u.getBluetoothUnoptimizedScanTimer(); + final long unoptimizedScanTotalTime = unoptimizedScanTimer != null ? + unoptimizedScanTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0; + final long unoptimizedScanMaxTime = unoptimizedScanTimer != null ? + unoptimizedScanTimer.getMaxDurationMsLocked(rawRealtimeMs) : 0; + // Unoptimized bg scan timer. Unpooled and since reset (regardless of 'which'). + final Timer unoptimizedScanTimerBg = + u.getBluetoothUnoptimizedScanBackgroundTimer(); + final long unoptimizedScanTotalTimeBg = unoptimizedScanTimerBg != null ? + unoptimizedScanTimerBg.getTotalDurationMsLocked(rawRealtimeMs) : 0; + final long unoptimizedScanMaxTimeBg = unoptimizedScanTimerBg != null ? + unoptimizedScanTimerBg.getMaxDurationMsLocked(rawRealtimeMs) : 0; + dumpLine(pw, uid, category, BLUETOOTH_MISC_DATA, totalTime, count, - countBg, actualTime, actualTimeBg, resultCount); + countBg, actualTime, actualTimeBg, resultCount, resultCountBg, + unoptimizedScanTotalTime, unoptimizedScanTotalTimeBg, + unoptimizedScanMaxTime, unoptimizedScanMaxTimeBg); } } @@ -3469,8 +3501,11 @@ public abstract class BatteryStats implements Parcelable { sb.setLength(0); linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, "f", which, linePrefix); - linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), + final Timer pTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); + linePrefix = printWakeLockCheckin(sb, pTimer, rawRealtime, "p", which, linePrefix); + linePrefix = printWakeLockCheckin(sb, pTimer != null ? pTimer.getSubTimer() : null, + rawRealtime, "bp", which, linePrefix); linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, "w", which, linePrefix); @@ -4625,34 +4660,94 @@ public abstract class BatteryStats implements Parcelable { final long actualTimeMs = bleTimer.getTotalDurationMsLocked(rawRealtimeMs); final long actualTimeMsBg = bleTimerBg != null ? bleTimerBg.getTotalDurationMsLocked(rawRealtimeMs) : 0; + // Result counters final int resultCount = u.getBluetoothScanResultCounter() != null ? u.getBluetoothScanResultCounter().getCountLocked(which) : 0; + final int resultCountBg = u.getBluetoothScanResultBgCounter() != null ? + u.getBluetoothScanResultBgCounter().getCountLocked(which) : 0; + // Unoptimized scan timer. Unpooled and since reset (regardless of 'which'). + final Timer unoptimizedScanTimer = u.getBluetoothUnoptimizedScanTimer(); + final long unoptimizedScanTotalTime = unoptimizedScanTimer != null ? + unoptimizedScanTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0; + final long unoptimizedScanMaxTime = unoptimizedScanTimer != null ? + unoptimizedScanTimer.getMaxDurationMsLocked(rawRealtimeMs) : 0; + // Unoptimized bg scan timer. Unpooled and since reset (regardless of 'which'). + final Timer unoptimizedScanTimerBg = + u.getBluetoothUnoptimizedScanBackgroundTimer(); + final long unoptimizedScanTotalTimeBg = unoptimizedScanTimerBg != null ? + unoptimizedScanTimerBg.getTotalDurationMsLocked(rawRealtimeMs) : 0; + final long unoptimizedScanMaxTimeBg = unoptimizedScanTimerBg != null ? + unoptimizedScanTimerBg.getMaxDurationMsLocked(rawRealtimeMs) : 0; sb.setLength(0); - sb.append(prefix); - sb.append(" "); - sb.append("Bluetooth Scan"); - sb.append(": "); if (actualTimeMs != totalTimeMs) { + sb.append(prefix); + sb.append(" Bluetooth Scan (total blamed realtime): "); formatTimeMs(sb, totalTimeMs); - sb.append("blamed realtime, "); + sb.append(" ("); + sb.append(count); + sb.append(" times)"); + if (bleTimer.isRunningLocked()) { + sb.append(" (currently running)"); + } + sb.append("\n"); } - formatTimeMs(sb, actualTimeMs); // since reset, regardless of 'which' - sb.append("realtime ("); + + sb.append(prefix); + sb.append(" Bluetooth Scan (total actual realtime): "); + formatTimeMs(sb, actualTimeMs); // since reset, ignores 'which' + sb.append(" ("); sb.append(count); sb.append(" times)"); if (bleTimer.isRunningLocked()) { - sb.append(" (running)"); + sb.append(" (currently running)"); } - if (actualTimeMsBg != 0 || countBg > 0) { - sb.append(", "); - formatTimeMs(sb, actualTimeMsBg); // since reset, regardless of 'which' - sb.append("background ("); + sb.append("\n"); + if (actualTimeMsBg > 0 || countBg > 0) { + sb.append(prefix); + sb.append(" Bluetooth Scan (background realtime): "); + formatTimeMs(sb, actualTimeMsBg); // since reset, ignores 'which' + sb.append(" ("); sb.append(countBg); sb.append(" times)"); + if (bleTimerBg != null && bleTimerBg.isRunningLocked()) { + sb.append(" (currently running in background)"); + } + sb.append("\n"); } - sb.append("; Results count "); + + sb.append(prefix); + sb.append(" Bluetooth Scan Results: "); sb.append(resultCount); + sb.append(" ("); + sb.append(resultCountBg); + sb.append(" in background)"); + + if (unoptimizedScanTotalTime > 0 || unoptimizedScanTotalTimeBg > 0) { + sb.append("\n"); + sb.append(prefix); + sb.append(" Unoptimized Bluetooth Scan (realtime): "); + formatTimeMs(sb, unoptimizedScanTotalTime); // since reset, ignores 'which' + sb.append(" (max "); + formatTimeMs(sb, unoptimizedScanMaxTime); // since reset, ignores 'which' + sb.append(")"); + if (unoptimizedScanTimer != null + && unoptimizedScanTimer.isRunningLocked()) { + sb.append(" (currently running unoptimized)"); + } + if (unoptimizedScanTimerBg != null && unoptimizedScanTotalTimeBg > 0) { + sb.append("\n"); + sb.append(prefix); + sb.append(" Unoptimized Bluetooth Scan (background realtime): "); + formatTimeMs(sb, unoptimizedScanTotalTimeBg); // since reset + sb.append(" (max "); + formatTimeMs(sb, unoptimizedScanMaxTimeBg); // since reset + sb.append(")"); + if (unoptimizedScanTimerBg.isRunningLocked()) { + sb.append(" (currently running unoptimized in background)"); + } + } + } pw.println(sb.toString()); uidActivity = true; } @@ -4696,8 +4791,11 @@ public abstract class BatteryStats implements Parcelable { sb.append(wakelocks.keyAt(iw)); linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, "full", which, linePrefix); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime, + final Timer pTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); + linePrefix = printWakeLock(sb, pTimer, rawRealtime, "partial", which, linePrefix); + linePrefix = printWakeLock(sb, pTimer != null ? pTimer.getSubTimer() : null, + rawRealtime, "background partial", which, linePrefix); linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, "window", which, linePrefix); linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime, diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index f361c549f016..d81ee4ef9843 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1642,11 +1642,20 @@ public class StorageManager { */ @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) @SystemApi - public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; + public static final int FLAG_ALLOCATE_AGGRESSIVE = 1 << 0; + + /** + * Flag indicating that a disk space allocation request should defy any + * reserved disk space. + * + * @hide + */ + public static final int FLAG_ALLOCATE_DEFY_RESERVED = 1 << 1; /** @hide */ @IntDef(flag = true, value = { FLAG_ALLOCATE_AGGRESSIVE, + FLAG_ALLOCATE_DEFY_RESERVED, }) @Retention(RetentionPolicy.SOURCE) public @interface AllocateFlags {} diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 5408e1319e36..70ef0355af8c 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -8915,15 +8915,11 @@ public final class ContactsContract { * ambiguous then the activity should prompt the user for the recipient to send the message * to. * <p> - * Voice Assistant may provide additional information to messaging app about which account - * to use for sending a message by populating {@link #EXTRA_SENDER_ACCOUNT_HASH}. - * <p> * Output: nothing * * @see #EXTRA_RECIPIENT_CONTACT_URI * @see #EXTRA_RECIPIENT_CONTACT_CHAT_ID * @see #EXTRA_RECIPIENT_CONTACT_NAME - * @see #EXTRA_SENDER_ACCOUNT_HASH * @see #METADATA_ACCOUNT_TYPE * @see #METADATA_MIMETYPE */ @@ -8982,21 +8978,6 @@ public final class ContactsContract { "android.provider.extra.RECIPIENT_CONTACT_NAME"; /** - * This optional extra specifies the hash of the account that should be used by messaging - * app for sending voice message with {@link #ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS}. The - * value of this extra is a {@code String} and should be the value of {@link - * android.accounts.Account#hashCode()} for some account returned by {@link - * android.accounts.AccountManager#getAccounts()}. - * <p> - * If the extra is not specified, the app can decide which account to use. - * <p> - * If the account specified in the extra cannot be used for any reason (account missing, not - * usable by the app, etc), the message should not be sent. - */ - public static final String EXTRA_SENDER_ACCOUNT_HASH = - "android.provider.extra.SENDER_ACCOUNT_HASH"; - - /** * A string associated with an {@link #ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS} activity * describing {@link RawContacts#ACCOUNT_TYPE} for the corresponding Contacts Provider * implementation. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 3cd54b8af39e..6a17ed1500bd 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9817,13 +9817,49 @@ public final class Settings { public static final String ENABLE_EPHEMERAL_FEATURE = "enable_ephemeral_feature"; /** - * The duration for caching uninstalled instant apps. + * The min period for caching installed instant apps in milliseconds. * <p> * Type: long * @hide */ - public static final String UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS = - "uninstalled_instant_app_cache_duration_millis"; + public static final String INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD = + "installed_instant_app_min_cache_period"; + + /** + * The max period for caching installed instant apps in milliseconds. + * <p> + * Type: long + * @hide + */ + public static final String INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD = + "installed_instant_app_max_cache_period"; + + /** + * The min period for caching uninstalled instant apps in milliseconds. + * <p> + * Type: long + * @hide + */ + public static final String UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD = + "uninstalled_instant_app_min_cache_period"; + + /** + * The max period for caching uninstalled instant apps in milliseconds. + * <p> + * Type: long + * @hide + */ + public static final String UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD = + "uninstalled_instant_app_max_cache_period"; + + /** + * The min period for caching unused static shared libs in milliseconds. + * <p> + * Type: long + * @hide + */ + public static final String UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD = + "unused_static_shared_lib_min_cache_period"; /** * Allows switching users when system user is locked. diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java index adf49387a05d..480abc1482a3 100644 --- a/core/java/android/util/proto/ProtoOutputStream.java +++ b/core/java/android/util/proto/ProtoOutputStream.java @@ -1593,7 +1593,7 @@ public final class ProtoOutputStream { assertNotCompacted(); final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED64); - writeRepeatedFixed64(id, val); + writeRepeatedFixed64Impl(id, val); } private void writeRepeatedFixed64Impl(int id, long val) { @@ -1720,7 +1720,7 @@ public final class ProtoOutputStream { assertNotCompacted(); final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED64); - writeRepeatedSFixed64(id, val); + writeRepeatedSFixed64Impl(id, val); } private void writeRepeatedSFixed64Impl(int id, long val) { @@ -1785,7 +1785,7 @@ public final class ProtoOutputStream { assertNotCompacted(); final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BOOL); - writeRepeatedBool(id, val); + writeRepeatedBoolImpl(id, val); } private void writeRepeatedBoolImpl(int id, boolean val) { diff --git a/core/java/android/view/AppTransitionAnimationSpec.java b/core/java/android/view/AppTransitionAnimationSpec.java index c6e1989e8b55..86a5fb761355 100644 --- a/core/java/android/view/AppTransitionAnimationSpec.java +++ b/core/java/android/view/AppTransitionAnimationSpec.java @@ -1,6 +1,6 @@ package android.view; -import android.graphics.Bitmap; +import android.graphics.GraphicBuffer; import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; @@ -15,19 +15,19 @@ import android.os.Parcelable; */ public class AppTransitionAnimationSpec implements Parcelable { public final int taskId; - public final Bitmap bitmap; + public final GraphicBuffer buffer; public final Rect rect; - public AppTransitionAnimationSpec(int taskId, Bitmap bitmap, Rect rect) { + public AppTransitionAnimationSpec(int taskId, GraphicBuffer buffer, Rect rect) { this.taskId = taskId; - this.bitmap = bitmap; this.rect = rect; + this.buffer = buffer; } public AppTransitionAnimationSpec(Parcel in) { taskId = in.readInt(); - bitmap = in.readParcelable(null); rect = in.readParcelable(null); + buffer = in.readParcelable(null); } @Override @@ -38,9 +38,8 @@ public class AppTransitionAnimationSpec implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(taskId); - dest.writeParcelable(bitmap, 0 /* flags */); dest.writeParcelable(rect, 0 /* flags */); - + dest.writeParcelable(buffer, 0); } public static final Parcelable.Creator<AppTransitionAnimationSpec> CREATOR @@ -56,6 +55,6 @@ public class AppTransitionAnimationSpec implements Parcelable { @Override public String toString() { - return "{taskId: " + taskId + ", bitmap: " + bitmap + ", rect: " + rect + "}"; + return "{taskId: " + taskId + ", buffer: " + buffer + ", rect: " + rect + "}"; } } diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl index dbeb747adfba..d2dcb568ef6c 100644 --- a/core/java/android/view/IPinnedStackController.aidl +++ b/core/java/android/view/IPinnedStackController.aidl @@ -30,6 +30,14 @@ interface IPinnedStackController { oneway void setIsMinimized(boolean isMinimized); /** + * Notifies the controller of the current min edge size, this is needed to allow the system to + * properly calculate the aspect ratio of the expanded PIP. The given {@param minEdgeSize} is + * always bounded to be larger than the default minEdgeSize, so the caller can call this method + * with 0 to reset to the default size. + */ + oneway void setMinEdgeSize(int minEdgeSize); + + /** * @return what WM considers to be the current device rotation. */ int getDisplayRotation(); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index a2ff4f787b61..58a6a5e78803 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -26,6 +26,7 @@ import com.android.internal.policy.IShortcutService; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.GraphicBuffer; import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; @@ -96,9 +97,9 @@ interface IWindowManager int startHeight); void overridePendingAppTransitionClipReveal(int startX, int startY, int startWidth, int startHeight); - void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY, + void overridePendingAppTransitionThumb(in GraphicBuffer srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp); - void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX, + void overridePendingAppTransitionAspectScaledThumb(in GraphicBuffer srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp); /** diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 2c9b2e4388f8..b57ac66e10cc 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -31,7 +31,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.Build; import android.os.Handler; -import android.os.Message; +import android.os.Looper; import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; @@ -120,34 +120,11 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb final Rect mTmpRect = new Rect(); final Configuration mConfiguration = new Configuration(); - static final int KEEP_SCREEN_ON_MSG = 1; - static final int DRAW_FINISHED_MSG = 2; - int mSubLayer = APPLICATION_MEDIA_SUBLAYER; boolean mIsCreating = false; private volatile boolean mRtHandlingPositionUpdates = false; - final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case KEEP_SCREEN_ON_MSG: { - setKeepScreenOn(msg.arg1 != 0); - } break; - case DRAW_FINISHED_MSG: { - mDrawFinished = true; - if (mAttachedToWindow) { - mParent.requestTransparentRegion(SurfaceView.this); - - notifyDrawFinished(); - invalidate(); - } - } break; - } - } - }; - private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() { @Override @@ -287,6 +264,22 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb updateSurface(); } + private void performDrawFinished() { + if (mPendingReportDraws > 0) { + mDrawFinished = true; + if (mAttachedToWindow) { + mParent.requestTransparentRegion(SurfaceView.this); + + notifyDrawFinished(); + invalidate(); + } + } else { + Log.e(TAG, System.identityHashCode(this) + "finished drawing" + + " but no pending report draw (extra call" + + " to draw completion runnable?)"); + } + } + void notifyDrawFinished() { ViewRootImpl viewRoot = getViewRootImpl(); if (viewRoot != null) { @@ -751,7 +744,9 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mDeferredDestroySurfaceControl = null; } - mHandler.sendEmptyMessage(DRAW_FINISHED_MSG); + runOnUiThread(() -> { + performDrawFinished(); + }); } private void setParentSpaceRectangle(Rect position, long frameNumber) { @@ -880,6 +875,15 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb + "type=" + type, new Throwable()); } + private void runOnUiThread(Runnable runnable) { + Handler handler = getHandler(); + if (handler != null && handler.getLooper() != Looper.myLooper()) { + handler.post(runnable); + } else { + runnable.run(); + } + } + /** * Check to see if the surface has fixed size dimensions or if the surface's * dimensions are dimensions are dependent on its current layout. @@ -960,9 +964,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb @Override public void setKeepScreenOn(boolean screenOn) { - Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG); - msg.arg1 = screenOn ? 1 : 0; - mHandler.sendMessage(msg); + runOnUiThread(() -> SurfaceView.this.setKeepScreenOn(screenOn)); } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 28ded55c54fa..a720aae0d1be 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2330,7 +2330,7 @@ public final class ViewRootImpl implements ViewParent, // Remember if we must report the next draw. if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { - mReportNextDraw = true; + reportNextDraw(); } boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible; @@ -2731,11 +2731,8 @@ public final class ViewRootImpl implements ViewParent, /** * A count of the number of calls to pendingDrawFinished we * require to notify the WM drawing is complete. - * - * This starts at 1, for the ViewRootImpl surface itself. - * Subsurfaces may debt the value with drawPending. */ - int mDrawsNeededToReport = 1; + int mDrawsNeededToReport = 0; /** * Delay notifying WM of draw finished until @@ -2761,7 +2758,7 @@ public final class ViewRootImpl implements ViewParent, private void reportDrawFinished() { try { - mDrawsNeededToReport = 1; + mDrawsNeededToReport = 0; mWindowSession.finishDrawing(mWindow); } catch (RemoteException e) { // Have fun! @@ -3772,13 +3769,12 @@ public final class ViewRootImpl implements ViewParent, args.recycle(); if (msg.what == MSG_RESIZED_REPORT) { - mReportNextDraw = true; + reportNextDraw(); } if (mView != null && framesChanged) { forceLayout(mView); } - requestLayout(); } break; @@ -7343,6 +7339,14 @@ public final class ViewRootImpl implements ViewParent, return false; } + + private void reportNextDraw() { + if (mReportNextDraw == false) { + drawPending(); + } + mReportNextDraw = true; + } + /** * Force the window to report its next draw. * <p> @@ -7352,7 +7356,7 @@ public final class ViewRootImpl implements ViewParent, * @hide */ public void setReportNextDraw() { - mReportNextDraw = true; + reportNextDraw(); invalidate(); } diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java index bf0e10f993ad..55aed529037d 100644 --- a/core/java/android/view/WindowManagerInternal.java +++ b/core/java/android/view/WindowManagerInternal.java @@ -225,6 +225,9 @@ public abstract class WindowManagerInternal { */ public abstract boolean isKeyguardLocked(); + /** @return {@code true} if the keyguard is going away. */ + public abstract boolean isKeyguardGoingAway(); + /** * Gets the frame of a window given its token. * diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index a2aff931ccff..02ecc501ea39 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -258,6 +258,11 @@ public final class AutofillManager { * @return The view, or {@code null} if not found */ @Nullable View findViewByAccessibilityIdTraversal(int viewId); + + /** + * Runs the specified action on the UI thread. + */ + void runOnUiThread(Runnable action); } /** @@ -1233,6 +1238,15 @@ public final class AutofillManager { return mService != null; } + private void post(Runnable runnable) { + final AutofillClient client = getClientLocked(); + if (client == null) { + if (sVerbose) Log.v(TAG, "ignoring post() because client is null"); + return; + } + client.runOnUiThread(runnable); + } + /** * View tracking information. Once all tracked views become invisible the session is finished. */ @@ -1516,8 +1530,7 @@ public final class AutofillManager { public void setState(boolean enabled, boolean resetSession, boolean resetClient) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post( - () -> afm.setState(enabled, resetSession, resetClient)); + afm.post(() -> afm.setState(enabled, resetSession, resetClient)); } } @@ -1525,8 +1538,7 @@ public final class AutofillManager { public void autofill(int sessionId, List<AutofillId> ids, List<AutofillValue> values) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post( - () -> afm.autofill(sessionId, ids, values)); + afm.post(() -> afm.autofill(sessionId, ids, values)); } } @@ -1535,8 +1547,7 @@ public final class AutofillManager { Intent fillInIntent) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post( - () -> afm.authenticate(sessionId, authenticationId, intent, fillInIntent)); + afm.post(() -> afm.authenticate(sessionId, authenticationId, intent, fillInIntent)); } } @@ -1545,9 +1556,8 @@ public final class AutofillManager { Rect anchorBounds, IAutofillWindowPresenter presenter) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post( - () -> afm.requestShowFillUi(sessionId, id, width, height, anchorBounds, - presenter)); + afm.post(() -> afm.requestShowFillUi(sessionId, id, width, height, anchorBounds, + presenter)); } } @@ -1555,7 +1565,7 @@ public final class AutofillManager { public void requestHideFillUi(int sessionId, AutofillId id) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> afm.requestHideFillUi(id)); + afm.post(() -> afm.requestHideFillUi(id)); } } @@ -1563,7 +1573,7 @@ public final class AutofillManager { public void notifyNoFillUi(int sessionId, AutofillId id) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> afm.notifyNoFillUi(sessionId, id)); + afm.post(() -> afm.notifyNoFillUi(sessionId, id)); } } @@ -1571,7 +1581,7 @@ public final class AutofillManager { public void startIntentSender(IntentSender intentSender) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { + afm.post(() -> { try { afm.mContext.startIntentSender(intentSender, null, 0, 0, 0); } catch (IntentSender.SendIntentException e) { @@ -1586,7 +1596,7 @@ public final class AutofillManager { boolean saveOnAllViewsInvisible, AutofillId[] fillableIds) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> + afm.post(() -> afm.setTrackedViews(sessionId, ids, saveOnAllViewsInvisible, fillableIds) ); } diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java index cd16a245c9b4..5f476380b1c3 100644 --- a/core/java/android/view/autofill/AutofillPopupWindow.java +++ b/core/java/android/view/autofill/AutofillPopupWindow.java @@ -16,6 +16,8 @@ package android.view.autofill; +import static android.view.autofill.Helper.sVerbose; + import android.annotation.NonNull; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -186,6 +188,10 @@ public class AutofillPopupWindow extends PopupWindow { @Override public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) { + if (sVerbose) { + Log.v(TAG, "showAsDropDown(): anchor=" + anchor + ", xoff=" + xoff + ", yoff=" + yoff + + ", isShowing(): " + isShowing()); + } if (isShowing()) { return; } diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 78566dfc458e..04f7c76c8e74 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -129,7 +129,7 @@ interface IBatteryStats { long getAwakeTimeBattery(); long getAwakeTimePlugged(); - void noteBleScanStarted(in WorkSource ws); + void noteBleScanStarted(in WorkSource ws, boolean isUnoptimized); void noteBleScanStopped(in WorkSource ws); void noteResetBleScan(); void noteBleScanResults(in WorkSource ws, int numNewResults); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 31064ac73dff..1b0d3323b3d0 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -56,6 +56,7 @@ import android.util.LogWriter; import android.util.LongSparseArray; import android.util.LongSparseLongArray; import android.util.MutableInt; +import android.util.Pools; import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; @@ -66,6 +67,7 @@ import android.util.TimeUtils; import android.util.Xml; import android.view.Display; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.NetworkStatsFactory; import com.android.internal.util.ArrayUtils; @@ -116,7 +118,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 158 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 159 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -173,7 +175,6 @@ public class BatteryStatsImpl extends BatteryStats { private final PlatformIdleStateCallback mPlatformIdleStateCallback; - final class MyHandler extends Handler { public MyHandler(Looper looper) { super(looper, null, true); @@ -228,11 +229,11 @@ public class BatteryStatsImpl extends BatteryStats { } public interface ExternalStatsSync { - public static final int UPDATE_CPU = 0x01; - public static final int UPDATE_WIFI = 0x02; - public static final int UPDATE_RADIO = 0x04; - public static final int UPDATE_BT = 0x08; - public static final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT; + int UPDATE_CPU = 0x01; + int UPDATE_WIFI = 0x02; + int UPDATE_RADIO = 0x04; + int UPDATE_BT = 0x08; + int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT; void scheduleSync(String reason, int flags); void scheduleCpuSyncDueToRemovedUid(int uid); @@ -572,8 +573,6 @@ public class BatteryStatsImpl extends BatteryStats { private int mMinLearnedBatteryCapacity = -1; private int mMaxLearnedBatteryCapacity = -1; - private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry(); - private long[] mCpuFreqs; private PowerProfile mPowerProfile; @@ -637,19 +636,9 @@ public class BatteryStatsImpl extends BatteryStats { private void init(Clocks clocks) { mClocks = clocks; - mMobileNetworkStats = new NetworkStats[] { - new NetworkStats(mClocks.elapsedRealtime(), 50), - new NetworkStats(mClocks.elapsedRealtime(), 50), - new NetworkStats(mClocks.elapsedRealtime(), 50) - }; - mWifiNetworkStats = new NetworkStats[] { - new NetworkStats(mClocks.elapsedRealtime(), 50), - new NetworkStats(mClocks.elapsedRealtime(), 50), - new NetworkStats(mClocks.elapsedRealtime(), 50) - }; } - public static interface TimeBaseObs { + public interface TimeBaseObs { void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime); void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime); } @@ -862,21 +851,19 @@ public class BatteryStatsImpl extends BatteryStats { final AtomicInteger mCount = new AtomicInteger(); final TimeBase mTimeBase; int mLoadedCount; - int mLastCount; int mUnpluggedCount; int mPluggedCount; - Counter(TimeBase timeBase, Parcel in) { + public Counter(TimeBase timeBase, Parcel in) { mTimeBase = timeBase; mPluggedCount = in.readInt(); mCount.set(mPluggedCount); mLoadedCount = in.readInt(); - mLastCount = 0; mUnpluggedCount = in.readInt(); timeBase.add(this); } - Counter(TimeBase timeBase) { + public Counter(TimeBase timeBase) { mTimeBase = timeBase; timeBase.add(this); } @@ -887,11 +874,12 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mUnpluggedCount); } + @Override public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { mUnpluggedCount = mPluggedCount; - mCount.set(mPluggedCount); } + @Override public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { mPluggedCount = mCount.get(); } @@ -926,17 +914,22 @@ public class BatteryStatsImpl extends BatteryStats { public void logState(Printer pw, String prefix) { pw.println(prefix + "mCount=" + mCount.get() - + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount + + " mLoadedCount=" + mLoadedCount + " mUnpluggedCount=" + mUnpluggedCount + " mPluggedCount=" + mPluggedCount); } - void stepAtomic() { - mCount.incrementAndGet(); + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public void stepAtomic() { + if (mTimeBase.isRunning()) { + mCount.incrementAndGet(); + } } void addAtomic(int delta) { - mCount.addAndGet(delta); + if (mTimeBase.isRunning()) { + mCount.addAndGet(delta); + } } /** @@ -944,7 +937,7 @@ public class BatteryStatsImpl extends BatteryStats { */ void reset(boolean detachIfReset) { mCount.set(0); - mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0; + mLoadedCount = mPluggedCount = mUnpluggedCount = 0; if (detachIfReset) { detach(); } @@ -954,15 +947,16 @@ public class BatteryStatsImpl extends BatteryStats { mTimeBase.remove(this); } - void writeSummaryFromParcelLocked(Parcel out) { + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public void writeSummaryFromParcelLocked(Parcel out) { int count = mCount.get(); out.writeInt(count); } - void readSummaryFromParcelLocked(Parcel in) { + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public void readSummaryFromParcelLocked(Parcel in) { mLoadedCount = in.readInt(); mCount.set(mLoadedCount); - mLastCount = 0; mUnpluggedCount = mPluggedCount = mLoadedCount; } } @@ -998,7 +992,6 @@ public class BatteryStatsImpl extends BatteryStats { @Override public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) { mUnpluggedCounts = copyArray(mPluggedCounts, mUnpluggedCounts); - mCounts = copyArray(mPluggedCounts, mCounts); } @Override @@ -1029,11 +1022,13 @@ public class BatteryStatsImpl extends BatteryStats { if (counts == null) { return; } - if (mCounts == null) { - mCounts = new long[counts.length]; - } - for (int i = 0; i < counts.length; ++i) { - mCounts[i] += counts[i]; + if (mTimeBase.isRunning()) { + if (mCounts == null) { + mCounts = new long[counts.length]; + } + for (int i = 0; i < counts.length; ++i) { + mCounts[i] += counts[i]; + } } } @@ -1104,13 +1099,13 @@ public class BatteryStatsImpl extends BatteryStats { } } - private void fillArray(long[] a, long val) { + private static void fillArray(long[] a, long val) { if (a != null) { Arrays.fill(a, val); } } - private void subtract(@NonNull long[] val, long[] toSubtract) { + private static void subtract(@NonNull long[] val, long[] toSubtract) { if (toSubtract == null) { return; } @@ -1119,7 +1114,7 @@ public class BatteryStatsImpl extends BatteryStats { } } - private long[] copyArray(long[] src, long[] dest) { + private static long[] copyArray(long[] src, long[] dest) { if (src == null) { return null; } else { @@ -1162,7 +1157,6 @@ public class BatteryStatsImpl extends BatteryStats { @Override public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { mUnpluggedCount = mPluggedCount; - mCount = mPluggedCount; } @Override @@ -1189,7 +1183,9 @@ public class BatteryStatsImpl extends BatteryStats { } void addCountLocked(long count) { - mCount += count; + if (mTimeBase.isRunning()) { + mCount += count; + } } /** @@ -4193,7 +4189,10 @@ public class BatteryStatsImpl extends BatteryStats { getUidStatsLocked(uid).noteMobileRadioApWakeupLocked(); } - public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) { + /** + * Updates the radio power state and returns true if an external stats collection should occur. + */ + public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) { final long elapsedRealtime = mClocks.elapsedRealtime(); final long uptime = mClocks.uptimeMillis(); if (mMobileRadioPowerState != powerState) { @@ -4230,13 +4229,15 @@ public class BatteryStatsImpl extends BatteryStats { mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime); } else { mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs); - updateMobileRadioStateLocked(realElapsedRealtimeMs, null); mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs); + // Tell the caller to collect radio network/power stats. + return true; } } + return false; } - public void notePowerSaveMode(boolean enabled) { + public void notePowerSaveModeLocked(boolean enabled) { if (mPowerSaveModeEnabled != enabled) { int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0; mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState; @@ -4821,7 +4822,7 @@ public class BatteryStatsImpl extends BatteryStats { } } - private void noteBluetoothScanStartedLocked(int uid) { + private void noteBluetoothScanStartedLocked(int uid, boolean isUnoptimized) { uid = mapUid(uid); final long elapsedRealtime = mClocks.elapsedRealtime(); final long uptime = mClocks.uptimeMillis(); @@ -4833,13 +4834,13 @@ public class BatteryStatsImpl extends BatteryStats { mBluetoothScanTimer.startRunningLocked(elapsedRealtime); } mBluetoothScanNesting++; - getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime); + getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized); } - public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws) { + public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) { final int N = ws.size(); for (int i = 0; i < N; i++) { - noteBluetoothScanStartedLocked(ws.get(i)); + noteBluetoothScanStartedLocked(ws.get(i), isUnoptimized); } } @@ -5236,28 +5237,26 @@ public class BatteryStatsImpl extends BatteryStats { public void noteNetworkInterfaceTypeLocked(String iface, int networkType) { if (TextUtils.isEmpty(iface)) return; - if (ConnectivityManager.isNetworkTypeMobile(networkType)) { - mMobileIfaces = includeInStringArray(mMobileIfaces, iface); - if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces); - } else { - mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface); - if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces); - } - if (ConnectivityManager.isNetworkTypeWifi(networkType)) { - mWifiIfaces = includeInStringArray(mWifiIfaces, iface); - if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces); - } else { - mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface); - if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces); + + synchronized (mModemNetworkLock) { + if (ConnectivityManager.isNetworkTypeMobile(networkType)) { + mModemIfaces = includeInStringArray(mModemIfaces, iface); + if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces); + } else { + mModemIfaces = excludeFromStringArray(mModemIfaces, iface); + if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces); + } } - } - public void noteNetworkStatsEnabledLocked() { - // During device boot, qtaguid isn't enabled until after the inital - // loading of battery stats. Now that they're enabled, take our initial - // snapshot for future delta calculation. - updateMobileRadioStateLocked(mClocks.elapsedRealtime(), null); - updateWifiStateLocked(null); + synchronized (mWifiNetworkLock) { + if (ConnectivityManager.isNetworkTypeWifi(networkType)) { + mWifiIfaces = includeInStringArray(mWifiIfaces, iface); + if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces); + } else { + mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface); + if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces); + } + } } @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) { @@ -5611,7 +5610,9 @@ public class BatteryStatsImpl extends BatteryStats { /** Total time spent by the uid holding any partial wakelocks. */ DualTimer mAggregatedPartialWakelockTimer; DualTimer mBluetoothScanTimer; + DualTimer mBluetoothUnoptimizedScanTimer; Counter mBluetoothScanResultCounter; + Counter mBluetoothScanResultBgCounter; int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT; StopwatchTimer[] mProcessStateTimer; @@ -6096,20 +6097,41 @@ public class BatteryStatsImpl extends BatteryStats { return mBluetoothScanTimer; } - public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs) { + public DualTimer createBluetoothUnoptimizedScanTimerLocked() { + if (mBluetoothUnoptimizedScanTimer == null) { + mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this, + BLUETOOTH_UNOPTIMIZED_SCAN_ON, null, + mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase); + } + return mBluetoothUnoptimizedScanTimer; + } + + public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized) { createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs); + if (isUnoptimized) { + createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs); + } } public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs) { if (mBluetoothScanTimer != null) { mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs); } + // In the ble code, a scan cannot change types and nested starts are not possible. + // So if an unoptimizedScan is running, it is now being stopped. + if (mBluetoothUnoptimizedScanTimer != null + && mBluetoothUnoptimizedScanTimer.isRunningLocked()) { + mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs); + } } public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) { if (mBluetoothScanTimer != null) { mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs); } + if (mBluetoothUnoptimizedScanTimer != null) { + mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs); + } } public Counter createBluetoothScanResultCounterLocked() { @@ -6119,8 +6141,17 @@ public class BatteryStatsImpl extends BatteryStats { return mBluetoothScanResultCounter; } + public Counter createBluetoothScanResultBgCounterLocked() { + if (mBluetoothScanResultBgCounter == null) { + mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase); + } + return mBluetoothScanResultBgCounter; + } + public void noteBluetoothScanResultsLocked(int numNewResults) { createBluetoothScanResultCounterLocked().addAtomic(numNewResults); + // Uses background timebase, so the count will only be incremented if uid in background. + createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults); } @Override @@ -6277,10 +6308,28 @@ public class BatteryStatsImpl extends BatteryStats { } @Override + public Timer getBluetoothUnoptimizedScanTimer() { + return mBluetoothUnoptimizedScanTimer; + } + + @Override + public Timer getBluetoothUnoptimizedScanBackgroundTimer() { + if (mBluetoothUnoptimizedScanTimer == null) { + return null; + } + return mBluetoothUnoptimizedScanTimer.getSubTimer(); + } + + @Override public Counter getBluetoothScanResultCounter() { return mBluetoothScanResultCounter; } + @Override + public Counter getBluetoothScanResultBgCounter() { + return mBluetoothScanResultBgCounter; + } + void makeProcessState(int i, Parcel in) { if (i < 0 || i >= NUM_PROCESS_STATE) return; @@ -6531,9 +6580,13 @@ public class BatteryStatsImpl extends BatteryStats { active |= !resetTimerIfNotNull(mForegroundActivityTimer, false); active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false); active |= !resetTimerIfNotNull(mBluetoothScanTimer, false); + active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false); if (mBluetoothScanResultCounter != null) { mBluetoothScanResultCounter.reset(false); } + if (mBluetoothScanResultBgCounter != null) { + mBluetoothScanResultBgCounter.reset(false); + } if (mProcessStateTimer != null) { for (int i = 0; i < NUM_PROCESS_STATE; i++) { @@ -6731,10 +6784,18 @@ public class BatteryStatsImpl extends BatteryStats { mBluetoothScanTimer.detach(); mBluetoothScanTimer = null; } + if (mBluetoothUnoptimizedScanTimer != null) { + mBluetoothUnoptimizedScanTimer.detach(); + mBluetoothUnoptimizedScanTimer = null; + } if (mBluetoothScanResultCounter != null) { mBluetoothScanResultCounter.detach(); mBluetoothScanResultCounter = null; } + if (mBluetoothScanResultBgCounter != null) { + mBluetoothScanResultBgCounter.detach(); + mBluetoothScanResultBgCounter = null; + } if (mUserActivityCounters != null) { for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { mUserActivityCounters[i].detach(); @@ -6919,12 +6980,24 @@ public class BatteryStatsImpl extends BatteryStats { } else { out.writeInt(0); } + if (mBluetoothUnoptimizedScanTimer != null) { + out.writeInt(1); + mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs); + } else { + out.writeInt(0); + } if (mBluetoothScanResultCounter != null) { out.writeInt(1); mBluetoothScanResultCounter.writeToParcel(out); } else { out.writeInt(0); } + if (mBluetoothScanResultBgCounter != null) { + out.writeInt(1); + mBluetoothScanResultBgCounter.writeToParcel(out); + } else { + out.writeInt(0); + } for (int i = 0; i < NUM_PROCESS_STATE; i++) { if (mProcessStateTimer[i] != null) { out.writeInt(1); @@ -7033,7 +7106,8 @@ public class BatteryStatsImpl extends BatteryStats { for (int j = 0; j < numWakelocks; j++) { String wakelockName = in.readString(); Uid.Wakelock wakelock = new Wakelock(mBsi, this); - wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in); + wakelock.readFromParcelLocked( + timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in); mWakelockStats.add(wakelockName, wakelock); } @@ -7168,10 +7242,22 @@ public class BatteryStatsImpl extends BatteryStats { mBluetoothScanTimer = null; } if (in.readInt() != 0) { + mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this, + BLUETOOTH_UNOPTIMIZED_SCAN_ON, null, + mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in); + } else { + mBluetoothUnoptimizedScanTimer = null; + } + if (in.readInt() != 0) { mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in); } else { mBluetoothScanResultCounter = null; } + if (in.readInt() != 0) { + mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in); + } else { + mBluetoothScanResultBgCounter = null; + } mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT; for (int i = 0; i < NUM_PROCESS_STATE; i++) { if (in.readInt() != 0) { @@ -7298,8 +7384,9 @@ public class BatteryStatsImpl extends BatteryStats { /** * How long (in ms) this uid has been keeping the device partially awake. + * Tracks both the total time and the time while the app was in the background. */ - DurationTimer mTimerPartial; + DualTimer mTimerPartial; /** * How long (in ms) this uid has been keeping the device fully awake. @@ -7344,13 +7431,13 @@ public class BatteryStatsImpl extends BatteryStats { * @param in the Parcel to be read from. * return a new Timer, or null. */ - private DurationTimer readDurationTimerFromParcel(int type, - ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) { + private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, + TimeBase timeBase, TimeBase bgTimeBase, Parcel in) { if (in.readInt() == 0) { return null; } - return new DurationTimer(mBsi.mClocks, mUid, type, pool, timeBase, in); + return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in); } boolean reset() { @@ -7388,9 +7475,10 @@ public class BatteryStatsImpl extends BatteryStats { return !wlactive; } - void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) { - mTimerPartial = readDurationTimerFromParcel(WAKE_TYPE_PARTIAL, - mBsi.mPartialTimers, screenOffTimeBase, in); + void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, + TimeBase screenOffBgTimeBase, Parcel in) { + mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL, + mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in); mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL, mBsi.mFullTimers, timeBase, in); mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW, @@ -7416,49 +7504,6 @@ public class BatteryStatsImpl extends BatteryStats { default: throw new IllegalArgumentException("type = " + type); } } - - public StopwatchTimer getStopwatchTimer(int type) { - switch (type) { - case WAKE_TYPE_PARTIAL: { - DurationTimer t = mTimerPartial; - if (t == null) { - t = new DurationTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL, - mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase); - mTimerPartial = t; - } - return t; - } - case WAKE_TYPE_FULL: { - StopwatchTimer t = mTimerFull; - if (t == null) { - t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_FULL, - mBsi.mFullTimers, mBsi.mOnBatteryTimeBase); - mTimerFull = t; - } - return t; - } - case WAKE_TYPE_WINDOW: { - StopwatchTimer t = mTimerWindow; - if (t == null) { - t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_WINDOW, - mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase); - mTimerWindow = t; - } - return t; - } - case WAKE_TYPE_DRAW: { - StopwatchTimer t = mTimerDraw; - if (t == null) { - t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_DRAW, - mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase); - mTimerDraw = t; - } - return t; - } - default: - throw new IllegalArgumentException("type=" + type); - } - } } public static class Sensor extends BatteryStats.Uid.Sensor { @@ -8351,16 +8396,16 @@ public class BatteryStatsImpl extends BatteryStats { Wakelock wl = new Wakelock(mBsi, this); mWakelockStats.add(wlName, wl); if (in.readInt() != 0) { - wl.getStopwatchTimer(WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); + getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in); } if (in.readInt() != 0) { - wl.getStopwatchTimer(WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); + getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in); } if (in.readInt() != 0) { - wl.getStopwatchTimer(WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); + getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in); } if (in.readInt() != 0) { - wl.getStopwatchTimer(WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in); + getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in); } } @@ -8416,10 +8461,57 @@ public class BatteryStatsImpl extends BatteryStats { } } + public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) { + if (wl == null) { + return null; + } + switch (type) { + case WAKE_TYPE_PARTIAL: { + DualTimer t = wl.mTimerPartial; + if (t == null) { + t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL, + mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase, + mOnBatteryScreenOffBackgroundTimeBase); + wl.mTimerPartial = t; + } + return t; + } + case WAKE_TYPE_FULL: { + StopwatchTimer t = wl.mTimerFull; + if (t == null) { + t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL, + mBsi.mFullTimers, mBsi.mOnBatteryTimeBase); + wl.mTimerFull = t; + } + return t; + } + case WAKE_TYPE_WINDOW: { + StopwatchTimer t = wl.mTimerWindow; + if (t == null) { + t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW, + mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase); + wl.mTimerWindow = t; + } + return t; + } + case WAKE_TYPE_DRAW: { + StopwatchTimer t = wl.mTimerDraw; + if (t == null) { + t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW, + mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase); + wl.mTimerDraw = t; + } + return t; + } + default: + throw new IllegalArgumentException("type=" + type); + } + } + public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) { Wakelock wl = mWakelockStats.startObject(name); if (wl != null) { - wl.getStopwatchTimer(type).startRunningLocked(elapsedRealtimeMs); + getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs); } if (type == WAKE_TYPE_PARTIAL) { createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs); @@ -8435,7 +8527,7 @@ public class BatteryStatsImpl extends BatteryStats { public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) { Wakelock wl = mWakelockStats.stopObject(name); if (wl != null) { - wl.getStopwatchTimer(type).stopRunningLocked(elapsedRealtimeMs); + getWakelockTimerLocked(wl, type).stopRunningLocked(elapsedRealtimeMs); } if (type == WAKE_TYPE_PARTIAL) { if (mAggregatedPartialWakelockTimer != null) { @@ -8613,27 +8705,25 @@ public class BatteryStatsImpl extends BatteryStats { mPlatformIdleStateCallback = null; } - public void setPowerProfile(PowerProfile profile) { - synchronized (this) { - mPowerProfile = profile; + public void setPowerProfileLocked(PowerProfile profile) { + mPowerProfile = profile; - // We need to initialize the KernelCpuSpeedReaders to read from - // the first cpu of each core. Once we have the PowerProfile, we have access to this - // information. - final int numClusters = mPowerProfile.getNumCpuClusters(); - mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters]; - int firstCpuOfCluster = 0; - for (int i = 0; i < numClusters; i++) { - final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i); - mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster, - numSpeedSteps); - firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i); - } + // We need to initialize the KernelCpuSpeedReaders to read from + // the first cpu of each core. Once we have the PowerProfile, we have access to this + // information. + final int numClusters = mPowerProfile.getNumCpuClusters(); + mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters]; + int firstCpuOfCluster = 0; + for (int i = 0; i < numClusters; i++) { + final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i); + mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster, + numSpeedSteps); + firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i); + } - if (mEstimatedBatteryCapacity == -1) { - // Initialize the estimated battery capacity to a known preset one. - mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity(); - } + if (mEstimatedBatteryCapacity == -1) { + // Initialize the estimated battery capacity to a known preset one. + mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity(); } } @@ -8641,7 +8731,7 @@ public class BatteryStatsImpl extends BatteryStats { mCallback = cb; } - public void setRadioScanningTimeout(long timeout) { + public void setRadioScanningTimeoutLocked(long timeout) { if (mPhoneSignalScanningTimer != null) { mPhoneSignalScanningTimer.setTimeout(timeout); } @@ -9333,277 +9423,293 @@ public class BatteryStatsImpl extends BatteryStats { } } - private String[] mMobileIfaces = EmptyArray.STRING; + private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory(); + private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6); + + private final Object mWifiNetworkLock = new Object(); + + @GuardedBy("mWifiNetworkLock") private String[] mWifiIfaces = EmptyArray.STRING; - private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory(); + @GuardedBy("mWifiNetworkLock") + private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1); - private static final int NETWORK_STATS_LAST = 0; - private static final int NETWORK_STATS_NEXT = 1; - private static final int NETWORK_STATS_DELTA = 2; + private final Object mModemNetworkLock = new Object(); - private NetworkStats[] mMobileNetworkStats; - private NetworkStats[] mWifiNetworkStats; + @GuardedBy("mModemNetworkLock") + private String[] mModemIfaces = EmptyArray.STRING; - /** - * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer - * as a buffer of NetworkStats objects to cycle through when computing deltas. - */ - private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces, - NetworkStats[] networkStatsBuffer) - throws IOException { - if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED, - false)) { - return null; - } + @GuardedBy("mModemNetworkLock") + private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1); - final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, - ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]); - networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats, - networkStatsBuffer[NETWORK_STATS_LAST], null, null, - networkStatsBuffer[NETWORK_STATS_DELTA]); - networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST]; - networkStatsBuffer[NETWORK_STATS_LAST] = stats; - return networkStatsBuffer[NETWORK_STATS_DELTA]; + private NetworkStats readNetworkStatsLocked(String[] ifaces) { + try { + if (!ArrayUtils.isEmpty(ifaces)) { + return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, + NetworkStats.TAG_NONE, mNetworkStatsPool.acquire()); + } + } catch (IOException e) { + Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces)); + } + return null; } /** * Distribute WiFi energy info and network traffic to apps. * @param info The energy information from the WiFi controller. */ - public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) { + public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) { if (DEBUG_ENERGY) { - Slog.d(TAG, "Updating wifi stats"); + Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces)); } - final long elapsedRealtimeMs = mClocks.elapsedRealtime(); + // Grab a separate lock to acquire the network stats, which may do I/O. NetworkStats delta = null; - try { - if (!ArrayUtils.isEmpty(mWifiIfaces)) { - delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats); + synchronized (mWifiNetworkLock) { + final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces); + if (latestStats != null) { + delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null, + mNetworkStatsPool.acquire()); + mNetworkStatsPool.release(mLastWifiNetworkStats); + mLastWifiNetworkStats = latestStats; } - } catch (IOException e) { - Slog.wtf(TAG, "Failed to get wifi network stats", e); - return; - } - - if (!mOnBatteryInternal) { - return; } - SparseLongArray rxPackets = new SparseLongArray(); - SparseLongArray txPackets = new SparseLongArray(); - long totalTxPackets = 0; - long totalRxPackets = 0; - if (delta != null) { - final int size = delta.size(); - for (int i = 0; i < size; i++) { - final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); - - if (DEBUG_ENERGY) { - Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes - + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets - + " txPackets=" + entry.txPackets); + synchronized (this) { + if (!mOnBatteryInternal) { + if (delta != null) { + mNetworkStatsPool.release(delta); } + return; + } - if (entry.rxBytes == 0 && entry.txBytes == 0) { - // Skip the lookup below since there is no work to do. - continue; - } + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); + SparseLongArray rxPackets = new SparseLongArray(); + SparseLongArray txPackets = new SparseLongArray(); + long totalTxPackets = 0; + long totalRxPackets = 0; + if (delta != null) { + NetworkStats.Entry entry = new NetworkStats.Entry(); + final int size = delta.size(); + for (int i = 0; i < size; i++) { + entry = delta.getValues(i, entry); - final Uid u = getUidStatsLocked(mapUid(entry.uid)); - if (entry.rxBytes != 0) { - u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, - entry.rxPackets); - if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers - u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes, - entry.rxPackets); + if (DEBUG_ENERGY) { + Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes + + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets + + " txPackets=" + entry.txPackets); } - mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxBytes); - mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxPackets); - - rxPackets.put(u.getUid(), entry.rxPackets); - // Sum the total number of packets so that the Rx Power can - // be evenly distributed amongst the apps. - totalRxPackets += entry.rxPackets; - } - - if (entry.txBytes != 0) { - u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, - entry.txPackets); - if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers - u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes, - entry.txPackets); + if (entry.rxBytes == 0 && entry.txBytes == 0) { + // Skip the lookup below since there is no work to do. + continue; } - mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txBytes); - mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txPackets); - txPackets.put(u.getUid(), entry.txPackets); + final Uid u = getUidStatsLocked(mapUid(entry.uid)); + if (entry.rxBytes != 0) { + u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, + entry.rxPackets); + if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers + u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes, + entry.rxPackets); + } + mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( + entry.rxBytes); + mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( + entry.rxPackets); - // Sum the total number of packets so that the Tx Power can - // be evenly distributed amongst the apps. - totalTxPackets += entry.txPackets; - } - } - } + rxPackets.put(u.getUid(), entry.rxPackets); - if (info != null) { - mHasWifiReporting = true; + // Sum the total number of packets so that the Rx Power can + // be evenly distributed amongst the apps. + totalRxPackets += entry.rxPackets; + } - // Measured in mAms - final long txTimeMs = info.getControllerTxTimeMillis(); - final long rxTimeMs = info.getControllerRxTimeMillis(); - final long idleTimeMs = info.getControllerIdleTimeMillis(); - final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs; + if (entry.txBytes != 0) { + u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, + entry.txPackets); + if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers + u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes, + entry.txPackets); + } + mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( + entry.txBytes); + mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( + entry.txPackets); - long leftOverRxTimeMs = rxTimeMs; - long leftOverTxTimeMs = txTimeMs; + txPackets.put(u.getUid(), entry.txPackets); - if (DEBUG_ENERGY) { - Slog.d(TAG, "------ BEGIN WiFi power blaming ------"); - Slog.d(TAG, " Tx Time: " + txTimeMs + " ms"); - Slog.d(TAG, " Rx Time: " + rxTimeMs + " ms"); - Slog.d(TAG, " Idle Time: " + idleTimeMs + " ms"); - Slog.d(TAG, " Total Time: " + totalTimeMs + " ms"); + // Sum the total number of packets so that the Tx Power can + // be evenly distributed amongst the apps. + totalTxPackets += entry.txPackets; + } + } + mNetworkStatsPool.release(delta); + delta = null; } - long totalWifiLockTimeMs = 0; - long totalScanTimeMs = 0; - - // On the first pass, collect some totals so that we can normalize power - // calculations if we need to. - final int uidStatsSize = mUidStats.size(); - for (int i = 0; i < uidStatsSize; i++) { - final Uid uid = mUidStats.valueAt(i); + if (info != null) { + mHasWifiReporting = true; - // Sum the total scan power for all apps. - totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked( - elapsedRealtimeMs * 1000) / 1000; + // Measured in mAms + final long txTimeMs = info.getControllerTxTimeMillis(); + final long rxTimeMs = info.getControllerRxTimeMillis(); + final long idleTimeMs = info.getControllerIdleTimeMillis(); + final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs; - // Sum the total time holding wifi lock for all apps. - totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked( - elapsedRealtimeMs * 1000) / 1000; - } - - if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) { - Slog.d(TAG, " !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > " - + rxTimeMs + " ms). Normalizing scan time."); - } - if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) { - Slog.d(TAG, " !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > " - + txTimeMs + " ms). Normalizing scan time."); - } + long leftOverRxTimeMs = rxTimeMs; + long leftOverTxTimeMs = txTimeMs; - // Actually assign and distribute power usage to apps. - for (int i = 0; i < uidStatsSize; i++) { - final Uid uid = mUidStats.valueAt(i); - - long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked( - elapsedRealtimeMs * 1000) / 1000; - if (scanTimeSinceMarkMs > 0) { - // Set the new mark so that next time we get new data since this point. - uid.mWifiScanTimer.setMark(elapsedRealtimeMs); + if (DEBUG_ENERGY) { + Slog.d(TAG, "------ BEGIN WiFi power blaming ------"); + Slog.d(TAG, " Tx Time: " + txTimeMs + " ms"); + Slog.d(TAG, " Rx Time: " + rxTimeMs + " ms"); + Slog.d(TAG, " Idle Time: " + idleTimeMs + " ms"); + Slog.d(TAG, " Total Time: " + totalTimeMs + " ms"); + } + + long totalWifiLockTimeMs = 0; + long totalScanTimeMs = 0; + + // On the first pass, collect some totals so that we can normalize power + // calculations if we need to. + final int uidStatsSize = mUidStats.size(); + for (int i = 0; i < uidStatsSize; i++) { + final Uid uid = mUidStats.valueAt(i); + + // Sum the total scan power for all apps. + totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked( + elapsedRealtimeMs * 1000) / 1000; + + // Sum the total time holding wifi lock for all apps. + totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked( + elapsedRealtimeMs * 1000) / 1000; + } + + if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) { + Slog.d(TAG, + " !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > " + + rxTimeMs + " ms). Normalizing scan time."); + } + if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) { + Slog.d(TAG, + " !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > " + + txTimeMs + " ms). Normalizing scan time."); + } + + // Actually assign and distribute power usage to apps. + for (int i = 0; i < uidStatsSize; i++) { + final Uid uid = mUidStats.valueAt(i); + + long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked( + elapsedRealtimeMs * 1000) / 1000; + if (scanTimeSinceMarkMs > 0) { + // Set the new mark so that next time we get new data since this point. + uid.mWifiScanTimer.setMark(elapsedRealtimeMs); + + long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; + long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; + + // Our total scan time is more than the reported Tx/Rx time. + // This is possible because the cost of a scan is approximate. + // Let's normalize the result so that we evenly blame each app + // scanning. + // + // This means that we may have apps that transmitted/received packets not be + // blamed for this, but this is fine as scans are relatively more expensive. + if (totalScanTimeMs > rxTimeMs) { + scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) / + totalScanTimeMs; + } + if (totalScanTimeMs > txTimeMs) { + scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) / + totalScanTimeMs; + } - long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; - long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; + if (DEBUG_ENERGY) { + Slog.d(TAG, " ScanTime for UID " + uid.getUid() + ": Rx:" + + scanRxTimeSinceMarkMs + " ms Tx:" + + scanTxTimeSinceMarkMs + " ms)"); + } - // Our total scan time is more than the reported Tx/Rx time. - // This is possible because the cost of a scan is approximate. - // Let's normalize the result so that we evenly blame each app - // scanning. - // - // This means that we may have apps that transmitted/received packets not be - // blamed for this, but this is fine as scans are relatively more expensive. - if (totalScanTimeMs > rxTimeMs) { - scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) / - totalScanTimeMs; - } - if (totalScanTimeMs > txTimeMs) { - scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) / - totalScanTimeMs; + ControllerActivityCounterImpl activityCounter = + uid.getOrCreateWifiControllerActivityLocked(); + activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs); + activityCounter.getTxTimeCounters()[0].addCountLocked( + scanTxTimeSinceMarkMs); + leftOverRxTimeMs -= scanRxTimeSinceMarkMs; + leftOverTxTimeMs -= scanTxTimeSinceMarkMs; } - if (DEBUG_ENERGY) { - Slog.d(TAG, " ScanTime for UID " + uid.getUid() + ": Rx:" - + scanRxTimeSinceMarkMs + " ms Tx:" - + scanTxTimeSinceMarkMs + " ms)"); + // Distribute evenly the power consumed while Idle to each app holding a WiFi + // lock. + final long wifiLockTimeSinceMarkMs = + uid.mFullWifiLockTimer.getTimeSinceMarkLocked( + elapsedRealtimeMs * 1000) / 1000; + if (wifiLockTimeSinceMarkMs > 0) { + // Set the new mark so that next time we get new data since this point. + uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs); + + final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) + / totalWifiLockTimeMs; + if (DEBUG_ENERGY) { + Slog.d(TAG, " IdleTime for UID " + uid.getUid() + ": " + + myIdleTimeMs + " ms"); + } + uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter() + .addCountLocked(myIdleTimeMs); } - - ControllerActivityCounterImpl activityCounter = - uid.getOrCreateWifiControllerActivityLocked(); - activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs); - activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs); - leftOverRxTimeMs -= scanRxTimeSinceMarkMs; - leftOverTxTimeMs -= scanTxTimeSinceMarkMs; } - // Distribute evenly the power consumed while Idle to each app holding a WiFi - // lock. - final long wifiLockTimeSinceMarkMs = uid.mFullWifiLockTimer.getTimeSinceMarkLocked( - elapsedRealtimeMs * 1000) / 1000; - if (wifiLockTimeSinceMarkMs > 0) { - // Set the new mark so that next time we get new data since this point. - uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs); + if (DEBUG_ENERGY) { + Slog.d(TAG, " New RxPower: " + leftOverRxTimeMs + " ms"); + Slog.d(TAG, " New TxPower: " + leftOverTxTimeMs + " ms"); + } - final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) - / totalWifiLockTimeMs; + // Distribute the remaining Tx power appropriately between all apps that transmitted + // packets. + for (int i = 0; i < txPackets.size(); i++) { + final Uid uid = getUidStatsLocked(txPackets.keyAt(i)); + final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) + / totalTxPackets; if (DEBUG_ENERGY) { - Slog.d(TAG, " IdleTime for UID " + uid.getUid() + ": " - + myIdleTimeMs + " ms"); + Slog.d(TAG, " TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms"); } - uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter() - .addCountLocked(myIdleTimeMs); + uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0] + .addCountLocked(myTxTimeMs); } - } - - if (DEBUG_ENERGY) { - Slog.d(TAG, " New RxPower: " + leftOverRxTimeMs + " ms"); - Slog.d(TAG, " New TxPower: " + leftOverTxTimeMs + " ms"); - } - // Distribute the remaining Tx power appropriately between all apps that transmitted - // packets. - for (int i = 0; i < txPackets.size(); i++) { - final Uid uid = getUidStatsLocked(txPackets.keyAt(i)); - final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) / totalTxPackets; - if (DEBUG_ENERGY) { - Slog.d(TAG, " TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms"); + // Distribute the remaining Rx power appropriately between all apps that received + // packets. + for (int i = 0; i < rxPackets.size(); i++) { + final Uid uid = getUidStatsLocked(rxPackets.keyAt(i)); + final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) + / totalRxPackets; + if (DEBUG_ENERGY) { + Slog.d(TAG, " RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms"); + } + uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter() + .addCountLocked(myRxTimeMs); } - uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0] - .addCountLocked(myTxTimeMs); - } - // Distribute the remaining Rx power appropriately between all apps that received - // packets. - for (int i = 0; i < rxPackets.size(); i++) { - final Uid uid = getUidStatsLocked(rxPackets.keyAt(i)); - final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets; - if (DEBUG_ENERGY) { - Slog.d(TAG, " RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms"); - } - uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter() - .addCountLocked(myRxTimeMs); - } + // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper. - // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper. - // Update WiFi controller stats. - mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis()); - mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis()); - mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis()); + // Update WiFi controller stats. + mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis()); + mWifiActivity.getTxTimeCounters()[0].addCountLocked( + info.getControllerTxTimeMillis()); + mWifiActivity.getIdleTimeCounter().addCountLocked( + info.getControllerIdleTimeMillis()); - // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V. - final double opVolt = mPowerProfile.getAveragePower( - PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0; - if (opVolt != 0) { - // We store the power drain as mAms. - mWifiActivity.getPowerCounter().addCountLocked( - (long)(info.getControllerEnergyUsed() / opVolt)); + // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V. + final double opVolt = mPowerProfile.getAveragePower( + PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0; + if (opVolt != 0) { + // We store the power drain as mAms. + mWifiActivity.getPowerCounter().addCountLocked( + (long) (info.getControllerEnergyUsed() / opVolt)); + } } } } @@ -9611,133 +9717,148 @@ public class BatteryStatsImpl extends BatteryStats { /** * Distribute Cell radio energy info and network traffic to apps. */ - public void updateMobileRadioStateLocked(final long elapsedRealtimeMs, - final ModemActivityInfo activityInfo) { + public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating mobile radio stats with " + activityInfo); } + // Grab a separate lock to acquire the network stats, which may do I/O. NetworkStats delta = null; - try { - if (!ArrayUtils.isEmpty(mMobileIfaces)) { - delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats); + synchronized (mModemNetworkLock) { + final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces); + if (latestStats != null) { + delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null, + mNetworkStatsPool.acquire()); + mNetworkStatsPool.release(mLastModemNetworkStats); + mLastModemNetworkStats = latestStats; } - } catch (IOException e) { - Slog.wtf(TAG, "Failed to get mobile network stats", e); - return; - } - - if (!mOnBatteryInternal) { - return; } - long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( - elapsedRealtimeMs * 1000); - mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs); - - long totalRxPackets = 0; - long totalTxPackets = 0; - if (delta != null) { - final int size = delta.size(); - for (int i = 0; i < size; i++) { - final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); - if (entry.rxPackets == 0 && entry.txPackets == 0) { - continue; - } - - if (DEBUG_ENERGY) { - Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes - + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets - + " txPackets=" + entry.txPackets); - } - - totalRxPackets += entry.rxPackets; - totalTxPackets += entry.txPackets; - - final Uid u = getUidStatsLocked(mapUid(entry.uid)); - u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets); - u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets); - if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers - u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA, - entry.rxBytes, entry.rxPackets); - u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA, - entry.txBytes, entry.txPackets); + synchronized (this) { + if (!mOnBatteryInternal) { + if (delta != null) { + mNetworkStatsPool.release(delta); } - - mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( - entry.rxBytes); - mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( - entry.txBytes); - mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( - entry.rxPackets); - mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( - entry.txPackets); + return; } - // Now distribute proportional blame to the apps that did networking. - long totalPackets = totalRxPackets + totalTxPackets; - if (totalPackets > 0) { + final long elapsedRealtimeMs = SystemClock.elapsedRealtime(); + long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( + elapsedRealtimeMs * 1000); + mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs); + + long totalRxPackets = 0; + long totalTxPackets = 0; + if (delta != null) { + NetworkStats.Entry entry = new NetworkStats.Entry(); + final int size = delta.size(); for (int i = 0; i < size; i++) { - final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry); + entry = delta.getValues(i, entry); if (entry.rxPackets == 0 && entry.txPackets == 0) { continue; } - final Uid u = getUidStatsLocked(mapUid(entry.uid)); + if (DEBUG_ENERGY) { + Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes + + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets + + " txPackets=" + entry.txPackets); + } - // Distribute total radio active time in to this app. - final long appPackets = entry.rxPackets + entry.txPackets; - final long appRadioTime = (radioTime * appPackets) / totalPackets; - u.noteMobileRadioActiveTimeLocked(appRadioTime); + totalRxPackets += entry.rxPackets; + totalTxPackets += entry.txPackets; + + final Uid u = getUidStatsLocked(mapUid(entry.uid)); + u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, + entry.rxPackets); + u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, + entry.txPackets); + if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers + u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA, + entry.rxBytes, entry.rxPackets); + u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA, + entry.txBytes, entry.txPackets); + } - // Remove this app from the totals, so that we don't lose any time - // due to rounding. - radioTime -= appRadioTime; - totalPackets -= appPackets; + mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( + entry.rxBytes); + mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( + entry.txBytes); + mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked( + entry.rxPackets); + mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked( + entry.txPackets); + } - if (activityInfo != null) { - ControllerActivityCounterImpl activityCounter = - u.getOrCreateModemControllerActivityLocked(); - if (totalRxPackets > 0 && entry.rxPackets > 0) { - final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis()) - / totalRxPackets; - activityCounter.getRxTimeCounter().addCountLocked(rxMs); + // Now distribute proportional blame to the apps that did networking. + long totalPackets = totalRxPackets + totalTxPackets; + if (totalPackets > 0) { + for (int i = 0; i < size; i++) { + entry = delta.getValues(i, entry); + if (entry.rxPackets == 0 && entry.txPackets == 0) { + continue; } - if (totalTxPackets > 0 && entry.txPackets > 0) { - for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { - long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl]; - txMs /= totalTxPackets; - activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs); + final Uid u = getUidStatsLocked(mapUid(entry.uid)); + + // Distribute total radio active time in to this app. + final long appPackets = entry.rxPackets + entry.txPackets; + final long appRadioTime = (radioTime * appPackets) / totalPackets; + u.noteMobileRadioActiveTimeLocked(appRadioTime); + + // Remove this app from the totals, so that we don't lose any time + // due to rounding. + radioTime -= appRadioTime; + totalPackets -= appPackets; + + if (activityInfo != null) { + ControllerActivityCounterImpl activityCounter = + u.getOrCreateModemControllerActivityLocked(); + if (totalRxPackets > 0 && entry.rxPackets > 0) { + final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis()) + / totalRxPackets; + activityCounter.getRxTimeCounter().addCountLocked(rxMs); + } + + if (totalTxPackets > 0 && entry.txPackets > 0) { + for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { + long txMs = + entry.txPackets * activityInfo.getTxTimeMillis()[lvl]; + txMs /= totalTxPackets; + activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs); + } } } } } - } - if (radioTime > 0) { - // Whoops, there is some radio time we can't blame on an app! - mMobileRadioActiveUnknownTime.addCountLocked(radioTime); - mMobileRadioActiveUnknownCount.addCountLocked(1); - } - } + if (radioTime > 0) { + // Whoops, there is some radio time we can't blame on an app! + mMobileRadioActiveUnknownTime.addCountLocked(radioTime); + mMobileRadioActiveUnknownCount.addCountLocked(1); + } - if (activityInfo != null) { - mHasModemReporting = true; - mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis()); - mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis()); - for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { - mModemActivity.getTxTimeCounters()[lvl] - .addCountLocked(activityInfo.getTxTimeMillis()[lvl]); + mNetworkStatsPool.release(delta); + delta = null; } - // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V. - final double opVolt = mPowerProfile.getAveragePower( - PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0; - if (opVolt != 0) { - // We store the power drain as mAms. - mModemActivity.getPowerCounter().addCountLocked( - (long) (activityInfo.getEnergyUsed() / opVolt)); + if (activityInfo != null) { + mHasModemReporting = true; + mModemActivity.getIdleTimeCounter().addCountLocked( + activityInfo.getIdleTimeMillis()); + mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis()); + for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { + mModemActivity.getTxTimeCounters()[lvl] + .addCountLocked(activityInfo.getTxTimeMillis()[lvl]); + } + + // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V. + final double opVolt = mPowerProfile.getAveragePower( + PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0; + if (opVolt != 0) { + // We store the power drain as mAms. + mModemActivity.getPowerCounter().addCountLocked( + (long) (activityInfo.getEnergyUsed() / opVolt)); + } } } } @@ -11380,8 +11501,14 @@ public class BatteryStatsImpl extends BatteryStats { u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in); } if (in.readInt() != 0) { + u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in); + } + if (in.readInt() != 0) { u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in); } + if (in.readInt() != 0) { + u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in); + } u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT; for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) { if (in.readInt() != 0) { @@ -11789,12 +11916,24 @@ public class BatteryStatsImpl extends BatteryStats { } else { out.writeInt(0); } + if (u.mBluetoothUnoptimizedScanTimer != null) { + out.writeInt(1); + u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); + } else { + out.writeInt(0); + } if (u.mBluetoothScanResultCounter != null) { out.writeInt(1); u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out); } else { out.writeInt(0); } + if (u.mBluetoothScanResultBgCounter != null) { + out.writeInt(1); + u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out); + } else { + out.writeInt(0); + } for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) { if (u.mProcessStateTimer[i] != null) { out.writeInt(1); diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java index ce89501c970a..66b777e8e8e6 100644 --- a/core/java/com/android/internal/util/DumpUtils.java +++ b/core/java/com/android/internal/util/DumpUtils.java @@ -31,7 +31,7 @@ import java.io.StringWriter; */ public final class DumpUtils { private static final String TAG = "DumpUtils"; - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; private DumpUtils() { } diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 369bb7f7b157..785fd2c4dd4f 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -16,7 +16,7 @@ #define ATRACE_TAG ATRACE_TAG_DALVIK #define LOG_TAG "AndroidRuntime" -//#define LOG_NDEBUG 0 +#define LOG_NDEBUG 1 #include <android_runtime/AndroidRuntime.h> #include <binder/IBinder.h> @@ -661,7 +661,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) checkJni = true; } } - ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF"); + ALOGV("CheckJNI is %s\n", checkJni ? "ON" : "OFF"); if (checkJni) { /* extended JNI checking */ addOption("-Xcheck:jni"); diff --git a/core/jni/android_hardware_Radio.cpp b/core/jni/android_hardware_Radio.cpp index b6b1ac75f0e9..18cf8caa9672 100644 --- a/core/jni/android_hardware_Radio.cpp +++ b/core/jni/android_hardware_Radio.cpp @@ -15,7 +15,7 @@ ** limitations under the License. */ -//#define LOG_NDEBUG 0 +#define LOG_NDEBUG 1 #define LOG_TAG "Radio-JNI" #include <utils/Log.h> @@ -955,7 +955,7 @@ int register_android_hardware_Radio(JNIEnv *env) int ret = RegisterMethodsOrDie(env, kRadioModuleClassPathName, gModuleMethods, NELEM(gModuleMethods)); - ALOGI("%s DONE", __FUNCTION__); + ALOGV("%s DONE", __FUNCTION__); return ret; } diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto index 8b73daf47f0f..e212c432558c 100644 --- a/core/proto/android/providers/settings.proto +++ b/core/proto/android/providers/settings.proto @@ -310,7 +310,7 @@ message GlobalSettingsProto { SettingProto lte_service_forced = 265; SettingProto ephemeral_cookie_max_size_bytes = 266; SettingProto enable_ephemeral_feature = 267; - SettingProto uninstalled_ephemeral_app_cache_duration_millis = 268; + SettingProto installed_instant_app_min_cache_period = 268; SettingProto allow_user_switching_when_system_user_locked = 269; SettingProto boot_count = 270; SettingProto safe_boot_disallowed = 271; @@ -331,6 +331,10 @@ message GlobalSettingsProto { SettingProto network_recommendations_package = 286; SettingProto bluetooth_a2dp_supports_optional_codecs_prefix = 287; SettingProto bluetooth_a2dp_optional_codecs_enabled_prefix = 288; + SettingProto installed_instant_app_max_cache_period = 289; + SettingProto uninstalled_instant_app_min_cache_period = 290; + SettingProto uninstalled_instant_app_max_cache_period = 291; + SettingProto unused_static_shared_lib_min_cache_period = 292; } message SecureSettingsProto { diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 3c42334be445..7e5a0816cba8 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -703,7 +703,7 @@ <string name="relationTypeFriend" msgid="7313106762483391262">"صديق"</string> <string name="relationTypeManager" msgid="6365677861610137895">"مدير"</string> <string name="relationTypeMother" msgid="4578571352962758304">"أم"</string> - <string name="relationTypeParent" msgid="4755635567562925226">"الأبوان"</string> + <string name="relationTypeParent" msgid="4755635567562925226">"الوالدان"</string> <string name="relationTypePartner" msgid="7266490285120262781">"شريك"</string> <string name="relationTypeReferredBy" msgid="101573059844135524">"جهة الإحالة"</string> <string name="relationTypeRelative" msgid="1799819930085610271">"قريب"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 649cadd400d4..06e60202d231 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -28,15 +28,15 @@ <string name="petabyteShort" msgid="5637816680144990219">"PB"</string> <string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string> <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dana"</string> - <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dan <xliff:g id="HOURS">%2$d</xliff:g> sati"</string> - <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dan <xliff:g id="HOURS">%2$d</xliff:g> sat"</string> + <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d i <xliff:g id="HOURS">%2$d</xliff:g> h"</string> + <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d i <xliff:g id="HOURS">%2$d</xliff:g> h"</string> <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> sati"</string> - <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> sat <xliff:g id="MINUTES">%2$d</xliff:g> min"</string> - <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> sat <xliff:g id="MINUTES">%2$d</xliff:g> min"</string> + <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h i <xliff:g id="MINUTES">%2$d</xliff:g> min"</string> + <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h i <xliff:g id="MINUTES">%2$d</xliff:g> min"</string> <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string> <string name="durationMinute" msgid="7155301744174623818">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string> - <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string> - <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string> + <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min i <xliff:g id="SECONDS">%2$d</xliff:g> s"</string> + <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min i <xliff:g id="SECONDS">%2$d</xliff:g> s"</string> <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sek"</string> <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sek"</string> <string name="untitled" msgid="4638956954852782576">"<Bez naslova>"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index c644866b7e7a..c5774cf3e1a7 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1116,7 +1116,7 @@ <string name="wifi_no_internet" msgid="8451173622563841546">"La Wi-Fi no té accés a Internet"</string> <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Toca per veure les opcions"</string> <string name="network_switch_metered" msgid="4671730921726992671">"Actualment en ús: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string> - <string name="network_switch_metered_detail" msgid="5325661434777870353">"El dispositiu utilitza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> en cas que <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tingui accés a Internet. És possible que s\'apliquin càrrecs."</string> + <string name="network_switch_metered_detail" msgid="5325661434777870353">"El dispositiu utilitza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> en cas que <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tingui accés a Internet. És possible que s\'hi apliquin càrrecs."</string> <string name="network_switch_metered_toast" msgid="5779283181685974304">"Abans es feia servir la xarxa <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>; ara s\'utilitza <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string> <string-array name="network_switch_type_name"> <item msgid="3979506840912951943">"dades mòbils"</item> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index e7f9a7f2cdf4..d2f8ecf1778c 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -291,7 +291,7 @@ <string name="permgroupdesc_camera" msgid="3250611594678347720">"사진 및 동영상 촬영"</string> <string name="permgrouplab_phone" msgid="5229115638567440675">"전화"</string> <string name="permgroupdesc_phone" msgid="6234224354060641055">"전화 걸기 및 관리"</string> - <string name="permgrouplab_sensors" msgid="416037179223226722">"신체 센서"</string> + <string name="permgrouplab_sensors" msgid="416037179223226722">"인체 감지 센서"</string> <string name="permgroupdesc_sensors" msgid="7147968539346634043">"생체 신호에 관한 센서 데이터에 액세스"</string> <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"창 콘텐츠 가져오기"</string> <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"상호작용 중인 창의 콘텐츠를 검사합니다."</string> @@ -381,7 +381,7 @@ <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"앱에서 수신 및 발신 통화 데이터를 포함하여 태블릿의 통화 기록을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 통화 기록을 지우거나 수정할 수 있습니다."</string> <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"앱에서 수신 및 발신 통화 데이터를 포함하여 TV의 통화 기록을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 통화 기록을 삭제하거나 수정할 수도 있습니다."</string> <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"앱에서 수신 및 발신 통화 데이터를 포함하여 휴대전화의 통화 기록을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 통화 기록을 지우거나 수정할 수 있습니다."</string> - <string name="permlab_bodySensors" msgid="4683341291818520277">"신체 센서(예: 심박수 모니터)에 액세스"</string> + <string name="permlab_bodySensors" msgid="4683341291818520277">"인체 감지 센서(예: 심박수 모니터)에 액세스"</string> <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"앱이 심박수와 같은 신체 상태를 확인하는 센서의 데이터에 접근하도록 허용합니다."</string> <string name="permlab_readCalendar" msgid="6716116972752441641">"캘린더 일정 및 세부정보 읽기"</string> <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"이 앱은 태블릿에 저장된 모든 캘린더 일정을 읽고 캘린더 데이터를 공유하거나 저장할 수 있습니다."</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 69fe42f642e7..0d5f04ac3b70 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -213,7 +213,7 @@ <string name="reboot_to_update_prepare" msgid="6305853831955310890">"Подготовка обновлений…"</string> <string name="reboot_to_update_package" msgid="3871302324500927291">"Обработка обновлений…"</string> <string name="reboot_to_update_reboot" msgid="6428441000951565185">"Перезагрузка…"</string> - <string name="reboot_to_reset_title" msgid="4142355915340627490">"Сбросить все данные"</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_confirm" product="tablet" msgid="3385745179555731470">"Планшетный ПК будет отключен."</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 51d932d16560..eb9994aed9de 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -152,8 +152,8 @@ <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> หลังผ่านไป <xliff:g id="TIME_DELAY">{2}</xliff:g> วินาที"</string> <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string> <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string> - <string name="fcComplete" msgid="3118848230966886575">"รหัสคุณลักษณะเสร็จสมบูรณ์"</string> - <string name="fcError" msgid="3327560126588500777">"พบปัญหาในการเชื่อมต่อหรือรหัสคุณลักษณะไม่ถูกต้อง"</string> + <string name="fcComplete" msgid="3118848230966886575">"รหัสฟีเจอร์เสร็จสมบูรณ์"</string> + <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> @@ -414,7 +414,7 @@ <string name="permlab_accessImsCallService" msgid="3574943847181793918">"เข้าถึงบริการโทร IMS"</string> <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"อนุญาตให้แอปใช้บริการ IMS เพื่อโทรออกโดยคุณไม่ต้องดำเนินการใดๆ เลย"</string> <string name="permlab_readPhoneState" msgid="9178228524507610486">"อ่านสถานะและข้อมูลระบุตัวตนของโทรศัพท์"</string> - <string name="permdesc_readPhoneState" msgid="1639212771826125528">"อนุญาตให้แอปพลิเคชันเข้าถึงคุณลักษณะโทรศัพท์ของอุปกรณ์ การอนุญาตนี้ทำให้แอปพลิเคชันสามารถตรวจสอบหมายเลขโทรศัพท์และรหัสอุปกรณ์ ตรวจสอบว่ามีการโทรที่ทำงานอยู่หรือไม่ และตรวจสอบหมายเลขระยะไกลที่เชื่อมต่อด้วยการโทร"</string> + <string name="permdesc_readPhoneState" msgid="1639212771826125528">"อนุญาตให้แอปพลิเคชันเข้าถึงฟีเจอร์โทรศัพท์ของอุปกรณ์ การอนุญาตนี้ทำให้แอปพลิเคชันสามารถตรวจสอบหมายเลขโทรศัพท์และรหัสอุปกรณ์ ตรวจสอบว่ามีการโทรที่ทำงานอยู่หรือไม่ และตรวจสอบหมายเลขระยะไกลที่เชื่อมต่อด้วยการโทร"</string> <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"กำหนดเส้นทางการโทรผ่านระบบ"</string> <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"อนุญาตให้แอปกำหนดเส้นทางการโทรของแอปผ่านระบบเพื่อปรับปรุงประสบการณ์ในการโทร"</string> <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"อ่านหมายเลขโทรศัพท์"</string> @@ -586,8 +586,8 @@ <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"ข้อมูลของแอปพลิเคชันที่จัดเก็บต้องมีการเข้ารหัส"</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> + <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"ปิดฟีเจอร์ล็อกหน้าจอบางอย่าง"</string> + <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"ป้องกันการใช้ฟีเจอร์บางอย่างของการล็อกหน้าจอ"</string> <string-array name="phoneTypes"> <item msgid="8901098336658710359">"บ้าน"</item> <item msgid="869923650527136615">"มือถือ"</item> @@ -722,7 +722,7 @@ <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"ถูกต้อง!"</string> <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"ลองอีกครั้ง"</string> <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ลองอีกครั้ง"</string> - <string name="lockscreen_storage_locked" msgid="9167551160010625200">"ปลดล็อกคุณลักษณะและข้อมูลทั้งหมด"</string> + <string name="lockscreen_storage_locked" msgid="9167551160010625200">"ปลดล็อกฟีเจอร์และข้อมูลทั้งหมด"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"มีความพยายามที่จะใช้ Face Unlock เกินขีดจำกัด"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ไม่มีซิมการ์ด"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ไม่มีซิมการ์ดในแท็บเล็ต"</string> @@ -842,7 +842,7 @@ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"อนุญาตให้แอปแก้ไขประวัติของเบราว์เซอร์หรือบุ๊กมาร์กที่เก็บไว้ในทีวี ซึ่งอาจอนุญาตให้แอปลบหรือแก้ไขข้อมูลเบราว์เซอร์ หมายเหตุ: สิทธิ์นี้ไม่สามารถใช้ได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นที่สามารถท่องเว็บได้"</string> <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บไว้ในโทรศัพท์ ซึ่งทำให้แอปพลิเคชันสามารถลบหรือเปลี่ยนข้อมูลเบราว์เซอร์ได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นๆ ที่มีความสามารถในการเรียกดูบนเว็บ"</string> <string name="permlab_setAlarm" msgid="1379294556362091814">"ตั้งปลุก"</string> - <string name="permdesc_setAlarm" msgid="316392039157473848">"อนุญาตให้แอปพลิเคชันตั้งเวลาปลุกในแอปพลิเคชันนาฬิกาปลุกที่ติดตั้ง แอปพลิเคชันนาฬิกาปลุกบางรายการอาจไม่ใช้คุณลักษณะนี้"</string> + <string name="permdesc_setAlarm" msgid="316392039157473848">"อนุญาตให้แอปพลิเคชันตั้งเวลาปลุกในแอปพลิเคชันนาฬิกาปลุกที่ติดตั้ง แอปพลิเคชันนาฬิกาปลุกบางรายการอาจไม่ใช้ฟีเจอร์นี้"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"เพิ่มข้อวามเสียง"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"อนุญาตให้แอปพลิเคชันเพิ่มข้อความลงในกล่องข้อความเสียงของคุณ"</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"แก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์"</string> @@ -1206,7 +1206,7 @@ <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string> <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> แสดงทับแอปอื่นๆ"</string> <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> กำลังแสดงทับแอปอื่นๆ"</string> - <string name="alert_windows_notification_message" msgid="8917232109522912560">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้คุณลักษณะนี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดคุณลักษณะ"</string> + <string name="alert_windows_notification_message" msgid="8917232109522912560">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้ฟีเจอร์นี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดฟีเจอร์"</string> <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ปิด"</string> <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"กำลังเตรียม <xliff:g id="NAME">%s</xliff:g>"</string> <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"กำลังตรวจหาข้อผิดพลาด"</string> @@ -1480,13 +1480,13 @@ <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"ลบ"</string> <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"นี่เป็นการเพิ่มระดับเสียงเกินระดับที่แนะนำ\n\nการฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"ใช้ทางลัดการเข้าถึงพิเศษไหม"</string> - <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"เมื่อทางลัดเปิดอยู่ การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มเป็นเวลา 3 วินาทีจะเริ่มคุณลักษณะการเข้าถึงพิเศษ\n\n คุณลักษณะการเข้าถึงพิเศษปัจจุบัน:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n คุณสามารถเปลี่ยนคุณลักษณะในการตั้งค่า > การเข้าถึงพิเศษ"</string> + <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"เมื่อทางลัดเปิดอยู่ การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มเป็นเวลา 3 วินาทีจะเริ่มฟีเจอร์การเข้าถึงพิเศษ\n\n ฟีเจอร์การเข้าถึงพิเศษปัจจุบัน:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n คุณสามารถเปลี่ยนฟีเจอร์ในการตั้งค่า > การเข้าถึงพิเศษ"</string> <string name="disable_accessibility_shortcut" msgid="627625354248453445">"ปิดทางลัด"</string> <string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"ใช้ทางลัด"</string> <string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"ทางลัดการเข้าถึงเปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string> <string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"ทางลัดการเข้าถึงปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string> - <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"เลือกคุณลักษณะที่จะใช้เมื่อคุณแตะปุ่ม \"การเข้าถึงพิเศษ\":"</string> - <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"หากต้องการเปลี่ยนคุณลักษณะ ให้แตะปุ่ม \"การเข้าถึงพิเศษ\" ค้างไว้"</string> + <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"เลือกฟีเจอร์ที่จะใช้เมื่อคุณแตะปุ่ม \"การเข้าถึงพิเศษ\":"</string> + <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"หากต้องการเปลี่ยนฟีเจอร์ ให้แตะปุ่ม \"การเข้าถึงพิเศษ\" ค้างไว้"</string> <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"การขยาย"</string> <string name="user_switched" msgid="3768006783166984410">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="user_switching_message" msgid="2871009331809089783">"กำลังเปลี่ยนเป็น <xliff:g id="NAME">%1$s</xliff:g>…"</string> @@ -1708,7 +1708,7 @@ <string name="region_picker_section_all" msgid="8966316787153001779">"ภูมิภาคทั้งหมด"</string> <string name="locale_search_menu" msgid="2560710726687249178">"ค้นหา"</string> <string name="work_mode_off_title" msgid="2615362773958585967">"เปิดโหมดงานไหม"</string> - <string name="work_mode_off_message" msgid="2961559609199223594">"การดำเนินการนี้จะเปิดโปรไฟล์งานของคุณ รวมถึงแอป การซิงค์ในพื้นหลัง และคุณลักษณะที่เกี่ยวข้อง"</string> + <string name="work_mode_off_message" msgid="2961559609199223594">"การดำเนินการนี้จะเปิดโปรไฟล์งานของคุณ รวมถึงแอป การซิงค์ในพื้นหลัง และฟีเจอร์ที่เกี่ยวข้อง"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"เปิด"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"คุณมีข้อความใหม่"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"เปิดแอป SMS เพื่อดู"</string> diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml index 75179463f0c4..8755e37f105f 100644 --- a/core/res/res/values/themes_device_defaults.xml +++ b/core/res/res/values/themes_device_defaults.xml @@ -758,6 +758,14 @@ easier. <item name="colorControlNormal">?attr/textColorPrimary</item> </style> + <style name="Theme.DeviceDefault.QuickSettings.Dialog" parent="Theme.DeviceDefault.Light.Dialog"> + <!-- Color palette --> + <item name="colorPrimary">@color/primary_device_default_settings_light</item> + <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item> + <item name="colorSecondary">@color/secondary_device_default_settings_light</item> + <item name="colorAccent">@color/accent_device_default_light</item> + </style> + <!-- Variant of {@link #Theme_DeviceDefault_Settings_Dark} with no action bar --> <style name="Theme.DeviceDefault.Settings.Dark.NoActionBar" parent="Theme.Material.NoActionBar"> <!-- Color palette --> diff --git a/core/tests/coretests/src/android/content/pm/AppCacheTest.java b/core/tests/coretests/src/android/content/pm/AppCacheTest.java index 15dbddff54df..59aa50ae1445 100644 --- a/core/tests/coretests/src/android/content/pm/AppCacheTest.java +++ b/core/tests/coretests/src/android/content/pm/AppCacheTest.java @@ -492,7 +492,7 @@ public class AppCacheTest extends AndroidTestCase { PackageDataObserver observer = new PackageDataObserver(); //wait on observer synchronized(observer) { - getPm().freeStorageAndNotify(null, idealStorageSize, observer); + getPm().freeStorageAndNotify(null, idealStorageSize, 0, observer); long waitTime = 0; while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) { observer.wait(WAIT_TIME_INCR); @@ -517,7 +517,7 @@ public class AppCacheTest extends AndroidTestCase { try { // Spin lock waiting for call back synchronized(r) { - getPm().freeStorage(null, idealStorageSize, pi.getIntentSender()); + getPm().freeStorage(null, idealStorageSize, 0, pi.getIntentSender()); long waitTime = 0; while(!r.isDone() && (waitTime < MAX_WAIT_TIME)) { r.wait(WAIT_TIME_INCR); diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 54d5285e3224..d875ed4e5ec5 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -334,7 +334,11 @@ public class SettingsBackupTest { Settings.Global.TRUSTED_SOUND, Settings.Global.TZINFO_UPDATE_CONTENT_URL, Settings.Global.TZINFO_UPDATE_METADATA_URL, - Settings.Global.UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS, + Settings.Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, + Settings.Global.INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD, + Settings.Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, + Settings.Global.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD, + Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD, Settings.Global.UNLOCK_SOUND, Settings.Global.USE_GOOGLE_MAIL, Settings.Global.VT_IMS_ENABLED, diff --git a/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java b/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java index fd57baa217b0..115af5e0ea5d 100644 --- a/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java +++ b/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java @@ -180,7 +180,9 @@ public class SparseMappingTableTest extends TestCase { try { table.getValue(key); - throw new Exception("Exception not thrown after mismatched reset calls."); + // Turn off this assertion because the check in SparseMappingTable.assertConsistency + // is also turned off. + //throw new Exception("Exception not thrown after mismatched reset calls."); } catch (RuntimeException ex) { // Good } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java index 9aabdbb2c8f0..c539f789ff60 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java @@ -205,9 +205,9 @@ public class BatteryStatsBackgroundStatsTest extends TestCase { // App in foreground bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND); - // Start timer + // Start timer (optimized) curr = 1000 * (clocks.realtime = clocks.uptime = 202); - bi.noteBluetoothScanStartedFromSourceLocked(ws); + bi.noteBluetoothScanStartedFromSourceLocked(ws, false); // Move to background curr = 1000 * (clocks.realtime = clocks.uptime = 254); @@ -221,21 +221,44 @@ public class BatteryStatsBackgroundStatsTest extends TestCase { curr = 1000 * (clocks.realtime = clocks.uptime = 409); bi.noteBluetoothScanStoppedFromSourceLocked(ws); + // Start timer (unoptimized) + curr = 1000 * (clocks.realtime = clocks.uptime = 1000); + bi.noteBluetoothScanStartedFromSourceLocked(ws, true); + + // On battery + curr = 1000 * (clocks.realtime = clocks.uptime = 2001); + bi.updateTimeBasesLocked(true, false, curr, curr); // on battery + + // Move to foreground + curr = 1000 * (clocks.realtime = clocks.uptime = 3004); + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); + + // Stop timer + curr = 1000 * (clocks.realtime = clocks.uptime = 4008); + bi.noteBluetoothScanStoppedFromSourceLocked(ws); + // Test - curr = 1000 * (clocks.realtime = clocks.uptime = 657); + curr = 1000 * (clocks.realtime = clocks.uptime = 5000); BatteryStats.Timer timer = bi.getUidStats().get(UID).getBluetoothScanTimer(); BatteryStats.Timer bgTimer = bi.getUidStats().get(UID).getBluetoothScanBackgroundTimer(); + BatteryStats.Timer badTimer = bi.getUidStats().get(UID).getBluetoothUnoptimizedScanTimer(); + BatteryStats.Timer badBgTimer = bi.getUidStats().get(UID) + .getBluetoothUnoptimizedScanBackgroundTimer(); long time = timer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED); int count = timer.getCountLocked(STATS_SINCE_CHARGED); int bgCount = bgTimer.getCountLocked(STATS_SINCE_CHARGED); long actualTime = timer.getTotalDurationMsLocked(clocks.realtime) * 1000; long bgTime = bgTimer.getTotalDurationMsLocked(clocks.realtime) * 1000; - assertEquals((305 - 202) * 1000, time); - assertEquals(1, count); - assertEquals(0, bgCount); - assertEquals((305 - 202) * 1000, actualTime); - assertEquals((305 - 254) * 1000, bgTime); + long badTime = badTimer.getTotalDurationMsLocked(clocks.realtime) * 1000; + long badBgTime = badBgTimer.getTotalDurationMsLocked(clocks.realtime) * 1000; + assertEquals((305 - 202 + 4008 - 2001) * 1000, time); + assertEquals(1, count); // second scan starts off-battery + assertEquals(0, bgCount); // first scan starts in fg, second starts off-battery + assertEquals((305 - 202 + 4008 - 2001) * 1000, actualTime); + assertEquals((305 - 254 + 3004 - 2001) * 1000, bgTime); + assertEquals((4008 - 2001) * 1000, badTime); + assertEquals((3004 - 2001) * 1000, badBgTime); } @SmallTest diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java new file mode 100644 index 000000000000..08f8dd146516 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java @@ -0,0 +1,148 @@ +/* + * 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 com.android.internal.os; + +import android.os.BatteryStats; +import android.os.Parcel; +import android.support.test.filters.SmallTest; + +import junit.framework.TestCase; + +/** + * Test BatteryStatsImpl.Counter. + */ +public class BatteryStatsCounterTest extends TestCase { + + @SmallTest + public void testCounter() throws Exception { + final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms + final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase(); + timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime()); + + final BatteryStatsImpl.Counter counter = new BatteryStatsImpl.Counter(timeBase); + + // timeBase off (i.e. plugged in) + timeBase.setRunning(false, 1, 1); + counter.stepAtomic(); + counter.stepAtomic(); + counter.stepAtomic(); + counter.stepAtomic(); + counter.stepAtomic(); + assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(0, counter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + + // timeBase on (i.e. unplugged) + timeBase.setRunning(true, 2, 2); + counter.stepAtomic(); + counter.stepAtomic(); + counter.stepAtomic(); + counter.stepAtomic(); + assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + + // timeBase off (i.e. plugged in) + timeBase.setRunning(false, 3, 3); + counter.stepAtomic(); + counter.stepAtomic(); + counter.stepAtomic(); + assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + + // timeBase on (i.e. unplugged) + timeBase.setRunning(true, 4, 4); + counter.stepAtomic(); + counter.stepAtomic(); + assertEquals(6, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(6, counter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(2, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + } + + + @SmallTest + public void testParceling() throws Exception { + final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms + final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase(); + timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime()); + + final BatteryStatsImpl.Counter origCounter = new BatteryStatsImpl.Counter(timeBase); + + // timeBase on (i.e. unplugged) + timeBase.setRunning(true, 1, 1); + origCounter.stepAtomic(); origCounter.stepAtomic(); origCounter.stepAtomic(); // three times + assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + + // Test summary parcelling (from origCounter) + final Parcel summaryParcel = Parcel.obtain(); + origCounter.writeSummaryFromParcelLocked(summaryParcel); + summaryParcel.setDataPosition(0); + final BatteryStatsImpl.Counter summaryCounter = new BatteryStatsImpl.Counter(timeBase); + summaryCounter.stepAtomic(); // occurs before reading the summary, so must not count later + summaryCounter.readSummaryFromParcelLocked(summaryParcel); + + // timeBase still on (i.e. unplugged) + summaryCounter.stepAtomic(); // once + assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + + // timeBase off (i.e. plugged in) + timeBase.setRunning(false, 3, 3); + summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice + assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + + // timeBase on (i.e. unplugged) + timeBase.setRunning(true, 4, 4); + summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice + assertEquals(6, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(3, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(2, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + + + // Test full parcelling (from summaryCounter) + final Parcel fullParcel = Parcel.obtain(); + summaryCounter.writeToParcel(fullParcel); + fullParcel.setDataPosition(0); + final BatteryStatsImpl.Counter fullParcelCounter + = new BatteryStatsImpl.Counter(timeBase, fullParcel); + + // timeBase still on (i.e. unplugged) + fullParcelCounter.stepAtomic(); // once + assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + + // timeBase off (i.e. plugged in) + timeBase.setRunning(false, 5, 5); + fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice + assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + + // timeBase on (i.e. unplugged) + timeBase.setRunning(true, 6, 6); + fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice + assertEquals(9, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(6, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT)); + assertEquals(2, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED)); + } +} diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java index 06ca18d072e7..4e8ab316e1c9 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java @@ -37,12 +37,28 @@ public class BatteryStatsNoteTest extends TestCase{ public void testNoteBluetoothScanResultLocked() throws Exception { MockBatteryStatsImpl bi = new MockBatteryStatsImpl(new MockClocks()); bi.updateTimeBasesLocked(true, true, 0, 0); + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); bi.noteBluetoothScanResultsFromSourceLocked(WS, 1); bi.noteBluetoothScanResultsFromSourceLocked(WS, 100); assertEquals(101, bi.getUidStats().get(UID).getBluetoothScanResultCounter() .getCountLocked(STATS_SINCE_CHARGED)); + // TODO: remove next line when Counter misreporting values when plugged-in bug is fixed. + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND); + BatteryStats.Counter bgCntr = bi.getUidStats().get(UID).getBluetoothScanResultBgCounter(); + if (bgCntr != null) { + assertEquals(0, bgCntr.getCountLocked(STATS_SINCE_CHARGED)); + } + + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND); + bi.noteBluetoothScanResultsFromSourceLocked(WS, 17); + assertEquals(101 + 17, + bi.getUidStats().get(UID).getBluetoothScanResultCounter() + .getCountLocked(STATS_SINCE_CHARGED)); + assertEquals(17, + bi.getUidStats().get(UID).getBluetoothScanResultBgCounter() + .getCountLocked(STATS_SINCE_CHARGED)); } /** Test BatteryStatsImpl.Uid.noteStartWakeLocked. */ diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java index 3a16fcff38a2..1412d3e7df59 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java @@ -5,17 +5,18 @@ import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ + BatteryStatsBackgroundStatsTest.class, + BatteryStatsCounterTest.class, BatteryStatsDualTimerTest.class, BatteryStatsDurationTimerTest.class, + BatteryStatsNoteTest.class, BatteryStatsSamplingTimerTest.class, + BatteryStatsSensorTest.class, BatteryStatsServTest.class, BatteryStatsStopwatchTimerTest.class, BatteryStatsTimeBaseTest.class, BatteryStatsTimerTest.class, BatteryStatsUidTest.class, - BatteryStatsSensorTest.class, - BatteryStatsBackgroundStatsTest.class, - BatteryStatsNoteTest.class, }) public class BatteryStatsTests { } diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index e62df8ff4742..e3b47405e0d4 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -529,6 +529,7 @@ public class Paint { setTextLocales(LocaleList.getAdjustedDefault()); setElegantTextHeight(false); mFontFeatureSettings = null; + mFontVariationSettings = null; } /** @@ -565,6 +566,7 @@ public class Paint { mBidiFlags = paint.mBidiFlags; mLocales = paint.mLocales; mFontFeatureSettings = paint.mFontFeatureSettings; + mFontVariationSettings = paint.mFontVariationSettings; } /** @hide */ @@ -1594,10 +1596,13 @@ public class Paint { return true; } + // The null typeface is valid and it is equivalent to Typeface.DEFAULT. + // To call isSupportedAxes method, use Typeface.DEFAULT instance. + Typeface targetTypeface = mTypeface == null ? Typeface.DEFAULT : mTypeface; FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings(settings); final ArrayList<FontVariationAxis> filteredAxes = new ArrayList<FontVariationAxis>(); for (final FontVariationAxis axis : axes) { - if (mTypeface.isSupportedAxes(axis.getOpenTypeTagValue())) { + if (targetTypeface.isSupportedAxes(axis.getOpenTypeTagValue())) { filteredAxes.add(axis); } } @@ -1605,7 +1610,7 @@ public class Paint { return false; } mFontVariationSettings = settings; - setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface, filteredAxes)); + setTypeface(Typeface.createFromTypefaceWithVariation(targetTypeface, filteredAxes)); return true; } diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 5a56f5335373..c4b56c333c64 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -725,8 +725,8 @@ public class Typeface { } /** @hide */ - public static Typeface createFromTypefaceWithVariation(Typeface family, - List<FontVariationAxis> axes) { + public static Typeface createFromTypefaceWithVariation(@Nullable Typeface family, + @NonNull List<FontVariationAxis> axes) { final long ni = family == null ? 0 : family.native_instance; return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes)); } @@ -1056,7 +1056,7 @@ public class Typeface { } } } - return Arrays.binarySearch(mSupportedAxes, axis) > 0; + return Arrays.binarySearch(mSupportedAxes, axis) >= 0; } private static native long nativeCreateFromTypeface(long native_instance, int style); diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index 39f11b8e6bfe..4ee47afe87fd 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -61,8 +61,17 @@ void RenderNodeDrawable::drawBackwardsProjectedNodes(SkCanvas* canvas, const Ski static void clipOutline(const Outline& outline, SkCanvas* canvas, const SkRect* pendingClip) { Rect possibleRect; float radius; - LOG_ALWAYS_FATAL_IF(!outline.getAsRoundRect(&possibleRect, &radius), - "clipping outlines should be at most roundedRects"); + + /* To match the existing HWUI behavior we only supports rectangles or + * rounded rectangles; passing in a more complicated outline fails silently. + */ + if (!outline.getAsRoundRect(&possibleRect, &radius)) { + if (pendingClip) { + canvas->clipRect(*pendingClip); + } + return; + } + SkRect rect = possibleRect.toSkRect(); if (radius != 0.0f) { if (pendingClip && !pendingClip->contains(rect)) { diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 02a9ffa3039c..cbc5163244c1 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -436,8 +436,15 @@ void CanvasContext::draw() { swap.vsyncTime = mRenderThread.timeLord().latestVsync(); if (mNativeSurface.get()) { int durationUs; - mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs); - swap.dequeueDuration = us2ns(durationUs); + nsecs_t dequeueStart = mNativeSurface->getLastDequeueStartTime(); + if (dequeueStart < mCurrentFrameInfo->get(FrameInfoIndex::Vsync)) { + // Ignoring dequeue duration as it happened prior to vsync + // and thus is not part of the frame. + swap.dequeueDuration = 0; + } else { + mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs); + swap.dequeueDuration = us2ns(durationUs); + } mNativeSurface->query(NATIVE_WINDOW_LAST_QUEUE_DURATION, &durationUs); swap.queueDuration = us2ns(durationUs); } else { diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 6cab56c1d466..2de69e7bc1de 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -75,12 +75,12 @@ import java.util.Map; <h4>Compressed Buffers</h4> <p> Input buffers (for decoders) and output buffers (for encoders) contain compressed data according - to the {@linkplain MediaFormat#KEY_MIME format's type}. For video types this is a single + to the {@linkplain MediaFormat#KEY_MIME format's type}. For video types this is normally a single compressed video frame. For audio data this is normally a single access unit (an encoded audio segment typically containing a few milliseconds of audio as dictated by the format type), but this requirement is slightly relaxed in that a buffer may contain multiple encoded access units of audio. In either case, buffers do not start or end on arbitrary byte boundaries, but rather on - frame/access unit boundaries. + frame/access unit boundaries unless they are flagged with {@link #BUFFER_FLAG_PARTIAL_FRAME}. <h4>Raw Audio Buffers</h4> <p> diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java index 5522d362bc09..799f4bf4f866 100644 --- a/media/java/android/media/MediaSync.java +++ b/media/java/android/media/MediaSync.java @@ -35,7 +35,7 @@ import java.util.LinkedList; import java.util.List; /** - * MediaSync class can be used to synchronously playback audio and video streams. + * MediaSync class can be used to synchronously play audio and video streams. * It can be used to play audio-only or video-only stream, too. * * <p>MediaSync is generally used like this: diff --git a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml index 2f0a411448a5..232459338f48 100644 --- a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml +++ b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml @@ -4,31 +4,35 @@ android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.android.captiveportallogin.CaptivePortalLoginActivity" - tools:ignore="MergeRootFrame"> + tools:ignore="MergeRootFrame" > + <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > - <TextView - android:id="@+id/url_bar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textSize="20sp" - android:singleLine="true" /> + <FrameLayout + android:layout_width="match_parent" + android:layout_height="4dp" > - <ProgressBar - android:id="@+id/progress_bar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="?android:attr/progressBarStyleHorizontal" /> + <!-- Eliminates ProgressBar padding by boxing it into a 4dp high container --> + <ProgressBar + android:id="@+id/progress_bar" + style="@android:style/Widget.Material.Light.ProgressBar.Horizontal" + android:indeterminate="false" + android:max="100" + android:progress="0" + android:layout_gravity="center" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + </FrameLayout> - <WebView - android:id="@+id/webview" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_alignParentBottom="false" - android:layout_alignParentRight="false" /> + <WebView + android:id="@+id/webview" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentBottom="false" + android:layout_alignParentRight="false" /> -</LinearLayout> + </LinearLayout> </FrameLayout> diff --git a/packages/CaptivePortalLogin/res/values/styles.xml b/packages/CaptivePortalLogin/res/values/styles.xml index 4a99638aec95..f6c233954b52 100644 --- a/packages/CaptivePortalLogin/res/values/styles.xml +++ b/packages/CaptivePortalLogin/res/values/styles.xml @@ -4,7 +4,7 @@ Base application theme, dependent on API level. This theme is replaced by AppBaseTheme from res/values-vXX/styles.xml on newer devices. --> - <style name="AppBaseTheme" parent="@android:style/Theme.Material.Settings"> + <style name="AppBaseTheme" parent="@android:style/Theme.DeviceDefault.Settings"> <!-- Theme customizations available in newer API levels can go in res/values-vXX/styles.xml, while customizations related to @@ -15,8 +15,5 @@ <!-- Application theme. --> <style name="AppTheme" parent="AppBaseTheme"> <!-- All customizations that are NOT specific to a particular API-level can go here. --> - <!-- Setting's theme's accent color makes ProgressBar useless, reset back. --> - <item name="android:colorAccent">@*android:color/material_deep_teal_500</item> </style> - </resources> diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index c9fba95bc828..401a7bca525c 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -37,6 +37,7 @@ import android.util.Log; import android.util.TypedValue; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.webkit.SslErrorHandler; import android.webkit.WebChromeClient; import android.webkit.WebSettings; @@ -97,8 +98,6 @@ public class CaptivePortalLoginActivity extends Activity { // setContentView initializes the WebView logic which in turn reads the system properties. setContentView(R.layout.activity_captive_portal_login); - getActionBar().setDisplayShowHomeEnabled(false); - // Exit app if Network disappears. final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork); if (networkCapabilities == null) { @@ -117,9 +116,14 @@ public class CaptivePortalLoginActivity extends Activity { } mCm.registerNetworkCallback(builder.build(), mNetworkCallback); - final WebView myWebView = findViewById(R.id.webview); - myWebView.clearCache(true); - WebSettings webSettings = myWebView.getSettings(); + getActionBar().setDisplayShowHomeEnabled(false); + getActionBar().setElevation(0); // remove shadow + getActionBar().setTitle(getHeaderTitle()); + getActionBar().setSubtitle(""); + + final WebView webview = getWebview(); + webview.clearCache(true); + WebSettings webSettings = webview.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE); webSettings.setUseWideViewPort(true); @@ -128,11 +132,11 @@ public class CaptivePortalLoginActivity extends Activity { webSettings.setBuiltInZoomControls(true); webSettings.setDisplayZoomControls(false); mWebViewClient = new MyWebViewClient(); - myWebView.setWebViewClient(mWebViewClient); - myWebView.setWebChromeClient(new MyWebChromeClient()); + webview.setWebViewClient(mWebViewClient); + webview.setWebChromeClient(new MyWebChromeClient()); // Start initial page load so WebView finishes loading proxy settings. // Actual load of mUrl is initiated by MyWebViewClient. - myWebView.loadData("", "text/html", null); + webview.loadData("", "text/html", null); } // Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties. @@ -251,10 +255,14 @@ public class CaptivePortalLoginActivity extends Activity { if (url == null) { url = mCm.getCaptivePortalServerUrl(); } + return makeURL(url); + } + + private static URL makeURL(String url) { try { return new URL(url); } catch (MalformedURLException e) { - Log.e(TAG, "Invalid captive portal URL " + url); + Log.e(TAG, "Invalid URL " + url); } return null; } @@ -331,15 +339,16 @@ public class CaptivePortalLoginActivity extends Activity { // For internally generated pages, leave URL bar listing prior URL as this is the URL // the page refers to. if (!url.startsWith(INTERNAL_ASSETS)) { - final TextView myUrlBar = findViewById(R.id.url_bar); - myUrlBar.setText(url); + getActionBar().setSubtitle(getHeaderSubtitle(url)); } + getProgressBar().setVisibility(View.VISIBLE); testForCaptivePortal(); } @Override public void onPageFinished(WebView view, String url) { mPagesLoaded++; + getProgressBar().setVisibility(View.INVISIBLE); if (mPagesLoaded == 1) { // Now that WebView has loaded at least one page we know it has read in the proxy // settings. Now prompt the WebView read the Network-specific proxy settings. @@ -412,8 +421,31 @@ public class CaptivePortalLoginActivity extends Activity { private class MyWebChromeClient extends WebChromeClient { @Override public void onProgressChanged(WebView view, int newProgress) { - final ProgressBar myProgressBar = findViewById(R.id.progress_bar); - myProgressBar.setProgress(newProgress); + getProgressBar().setProgress(newProgress); + } + } + + private ProgressBar getProgressBar() { + return findViewById(R.id.progress_bar); + } + + private WebView getWebview() { + return findViewById(R.id.webview); + } + + private String getHeaderTitle() { + return getString(R.string.action_bar_label); + } + + private String getHeaderSubtitle(String urlString) { + URL url = makeURL(urlString); + if (url == null) { + return urlString; + } + final String https = "https"; + if (https.equals(url.getProtocol())) { + return https + "://" + url.getHost(); } + return url.getHost(); } } diff --git a/packages/SettingsLib/res/layout/usage_view.xml b/packages/SettingsLib/res/layout/usage_view.xml index 151d1ee3b899..da66814f49cb 100644 --- a/packages/SettingsLib/res/layout/usage_view.xml +++ b/packages/SettingsLib/res/layout/usage_view.xml @@ -76,7 +76,7 @@ android:id="@+id/bottom_label_space" android:layout_width="@dimen/usage_graph_labels_width" android:layout_height="wrap_content"/> - <LinearLayout + <com.android.settingslib.graph.BottomLabelLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" @@ -86,13 +86,14 @@ layout="@layout/usage_side_label" /> <Space - android:layout_width="0dp" + android:id="@+id/spacer" + android:layout_width="40dp" android:layout_height="wrap_content" android:layout_weight="1" /> <include android:id="@+id/label_end" layout="@layout/usage_side_label" /> - </LinearLayout> + </com.android.settingslib.graph.BottomLabelLayout> </LinearLayout> </LinearLayout> diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java index 34fdc9ddd99d..a8f6f025b6d5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java @@ -63,15 +63,17 @@ public class StorageStatsSource { public long audioBytes; public long videoBytes; public long imageBytes; + public long appBytes; /** Convenience method for testing. */ @VisibleForTesting public ExternalStorageStats( - long totalBytes, long audioBytes, long videoBytes, long imageBytes) { + long totalBytes, long audioBytes, long videoBytes, long imageBytes, long appBytes) { this.totalBytes = totalBytes; this.audioBytes = audioBytes; this.videoBytes = videoBytes; this.imageBytes = imageBytes; + this.appBytes = appBytes; } /** @@ -84,6 +86,7 @@ public class StorageStatsSource { audioBytes = stats.getAudioBytes(); videoBytes = stats.getVideoBytes(); imageBytes = stats.getImageBytes(); + appBytes = stats.getAppBytes(); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java b/packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java new file mode 100644 index 000000000000..8161dd4bb934 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java @@ -0,0 +1,97 @@ +/* + * 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 com.android.settingslib.graph; + +import android.annotation.Nullable; +import android.content.Context; +import android.support.annotation.VisibleForTesting; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; + +import com.android.settingslib.R; + +/** + * An extension of LinearLayout that automatically switches to vertical + * orientation when it can't fit its child views horizontally. + * + * Main logic in this class comes from {@link android.support.v7.widget.ButtonBarLayout}. + * Compared with {@link android.support.v7.widget.ButtonBarLayout}, this layout won't reverse + * children's order and won't update the minimum height + */ +public class BottomLabelLayout extends LinearLayout { + private static final String TAG = "BottomLabelLayout"; + + public BottomLabelLayout(Context context, + @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int widthSize = MeasureSpec.getSize(widthMeasureSpec); + final boolean isStacked = isStacked(); + boolean needsRemeasure = false; + + // If we're not stacked, make sure the measure spec is AT_MOST rather + // than EXACTLY. This ensures that we'll still get TOO_SMALL so that we + // know to stack the buttons. + final int initialWidthMeasureSpec; + if (!isStacked && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) { + initialWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST); + + // We'll need to remeasure again to fill excess space. + needsRemeasure = true; + } else { + initialWidthMeasureSpec = widthMeasureSpec; + } + + super.onMeasure(initialWidthMeasureSpec, heightMeasureSpec); + if (!isStacked) { + final int measuredWidth = getMeasuredWidthAndState(); + final int measuredWidthState = measuredWidth & View.MEASURED_STATE_MASK; + + if (measuredWidthState == View.MEASURED_STATE_TOO_SMALL) { + setStacked(true); + // Measure again in the new orientation. + needsRemeasure = true; + } + } + + if (needsRemeasure) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + } + + @VisibleForTesting + void setStacked(boolean stacked) { + setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL); + setGravity(stacked ? Gravity.START : Gravity.BOTTOM); + + final View spacer = findViewById(R.id.spacer); + if (spacer != null) { + spacer.setVisibility(stacked ? View.GONE : View.VISIBLE); + } + } + + private boolean isStacked() { + return getOrientation() == LinearLayout.VERTICAL; + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java new file mode 100644 index 000000000000..ec217230af95 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java @@ -0,0 +1,70 @@ +/* + * 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 com.android.settingslib.graph; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.Space; + +import com.android.settingslib.R; +import com.android.settingslib.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class BottomLabelLayoutTest { + private BottomLabelLayout mBottomLabelLayout; + private Context mContext; + private Space mSpace; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mBottomLabelLayout = new BottomLabelLayout(mContext, null); + mBottomLabelLayout.setOrientation(LinearLayout.HORIZONTAL); + + mSpace = new Space(mContext); + mSpace.setId(R.id.spacer); + mBottomLabelLayout.addView(mSpace); + } + + @Test + public void testSetStacked_stackedTrue_layoutVertical() { + mBottomLabelLayout.setStacked(true); + + assertThat(mBottomLabelLayout.getOrientation()).isEqualTo(LinearLayout.VERTICAL); + assertThat(mSpace.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void testSetStacked_stackedFalse_layoutHorizontal() { + mBottomLabelLayout.setStacked(false); + + assertThat(mBottomLabelLayout.getOrientation()).isEqualTo(LinearLayout.HORIZONTAL); + assertThat(mSpace.getVisibility()).isEqualTo(View.VISIBLE); + } +} diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 930935914967..b328933cd1c5 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -888,8 +888,20 @@ class SettingsProtoDumpUtil { Settings.Global.ENABLE_EPHEMERAL_FEATURE, GlobalSettingsProto.ENABLE_EPHEMERAL_FEATURE); dumpSetting(s, p, - Settings.Global.UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS, - GlobalSettingsProto.UNINSTALLED_EPHEMERAL_APP_CACHE_DURATION_MILLIS); + Settings.Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, + GlobalSettingsProto.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD); + dumpSetting(s, p, + Settings.Global.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD, + GlobalSettingsProto.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD); + dumpSetting(s, p, + Settings.Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, + GlobalSettingsProto.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD); + dumpSetting(s, p, + Settings.Global.INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD, + GlobalSettingsProto.INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD); + dumpSetting(s, p, + Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD, + GlobalSettingsProto.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD); dumpSetting(s, p, Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, GlobalSettingsProto.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED); diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 1ddbcad8e844..348b02aeda4a 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -966,17 +966,24 @@ public class BugreportProgressService extends Service { } final Intent notifIntent; + boolean useChooser = true; // Send through warning dialog by default if (getWarningState(mContext, STATE_UNKNOWN) != STATE_HIDE) { notifIntent = buildWarningIntent(mContext, sendIntent); + // No need to show a chooser in this case. + useChooser = false; } else { notifIntent = sendIntent; } notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Send the share intent... - sendShareIntent(mContext, notifIntent); + if (useChooser) { + sendShareIntent(mContext, notifIntent); + } else { + mContext.startActivity(notifIntent); + } // ... and stop watching this process. stopProgress(id); diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 79b02a5286e0..c4e134b92ec7 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -531,7 +531,7 @@ <activity android:name=".settings.BrightnessDialog" android:label="@string/quick_settings_brightness_dialog_title" - android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" + android:theme="@*android:style/Theme.DeviceDefault.QuickSettings.Dialog" android:finishOnCloseSystemDialogs="true" android:launchMode="singleInstance" android:excludeFromRecents="true" diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml deleted file mode 100644 index 195849a932be..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32.0dp" - android:height="32dp" - android:viewportWidth="12.0" - android:viewportHeight="12.0"> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M8.600000,5.500000l1.200000,-3.000000l1.900000,0.000000L9.700000,6.700000l2.200000,4.300000L9.900000,11.000000L8.700000,7.900000L7.400000,11.000000L5.500000,11.000000l2.100000,-4.300000L5.600000,2.500000l1.900000,0.000000L8.600000,5.500000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml deleted file mode 100644 index 68c43074d33f..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32dp" - android:height="32dp" - android:viewportWidth="13.0" - android:viewportHeight="13.0"> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M12.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S6.700000,9.000000 6.700000,7.900000L6.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000l-1.600000,0.000000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000s-0.500000,-0.300000 -0.900000,-0.300000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S8.400000,5.000000 8.400000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L10.799999,7.800000L9.600000,7.800000L9.600000,6.600000l2.900000,0.000000L12.500000,9.900000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml deleted file mode 100644 index 61ecc9c02a45..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32.0dp" - android:height="32dp" - android:viewportWidth="12.0" - android:viewportHeight="12.0"> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M11.900000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S6.100000,9.000000 6.100000,7.900000L6.100000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000S8.100000,2.400000 9.000000,2.400000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000l-1.600000,0.000000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S9.500000,3.700000 9.000000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S7.700000,5.000000 7.700000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L10.099999,7.800000L9.000000,7.800000L9.000000,6.600000l2.900000,0.000000L11.900000,9.900000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml deleted file mode 100644 index 782fbe4853d3..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- - Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32.0dp" - android:height="32.0dp" - android:viewportWidth="19.0" - android:viewportHeight="19.0"> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml deleted file mode 100644 index dd5843d1183a..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32dp" - android:height="32dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M21.799999,22.299999l-1.199999,-1.299999 0.000000,0.000000 -9.600000,-10.000000 0.000000,0.000000 -6.400000,-6.700000 -1.300000,1.300000 6.400000,6.700000 -8.700000,8.700000 16.900000,0.000000 2.600000,2.700001z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M21.000000,1.000000l-8.600000,8.600000 8.600000,9.100000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml deleted file mode 100644 index 42321263f397..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32dp" - android:height="32dp" - android:viewportWidth="13.0" - android:viewportHeight="13.0"> - <group - android:translateX="3.5" > - <path - android:fillColor="#FFFFFFFF" - android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/> - </group> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml deleted file mode 100644 index 0c512d74ce31..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml +++ /dev/null @@ -1,26 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32dp" - android:height="32dp" - android:viewportWidth="13.0" - android:viewportHeight="13.0"> - <group android:translateX="3.5" > - <path - android:fillColor="#FFFFFFFF" - android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/> - </group> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml deleted file mode 100644 index b9572b26501b..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32dp" - android:height="32dp" - android:viewportWidth="13.0" - android:viewportHeight="13.0"> - <group - android:translateX="3.5" > - <path - android:fillColor="#FFFFFFFF" - android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/> - </group> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml deleted file mode 100644 index a381d03e272a..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32dp" - android:height="32dp" - android:viewportWidth="13.0" - android:viewportHeight="13.0"> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M8.300000,3.800000L7.000000,3.800000L7.000000,11.000000L5.300000,11.000000L5.300000,3.800000L4.000000,3.800000L4.000000,2.500000l4.300000,0.000000L8.300000,3.800000z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M12.400000,7.300000l-1.700000,0.000000l0.000000,2.400000l2.100000,0.000000L12.799999,11.000000L9.000000,11.000000L9.000000,2.500000l3.700000,0.000000l0.000000,1.300000l-2.100000,0.000000l0.000000,2.100000l1.700000,0.000000L12.300000,7.300000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml deleted file mode 100644 index 3bed28a33609..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml +++ /dev/null @@ -1,33 +0,0 @@ -<!-- - Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32.0dp" - android:height="32.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/> -</vector> diff --git a/packages/SystemUI/res/layout/qs_footer.xml b/packages/SystemUI/res/layout/qs_footer.xml index 577be2fd684b..871d1f361dd0 100644 --- a/packages/SystemUI/res/layout/qs_footer.xml +++ b/packages/SystemUI/res/layout/qs_footer.xml @@ -27,6 +27,7 @@ android:clipChildren="false" android:clipToPadding="false" android:paddingTop="0dp" + android:background="#00000000" android:gravity="center_vertical" android:orientation="horizontal"> diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml index 005e9552a554..66c5dd5b5275 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml @@ -29,7 +29,6 @@ android:clickable="false" android:clipChildren="false" android:clipToPadding="false" - android:paddingBottom="48dp" android:paddingTop="0dp" android:paddingEnd="0dp" android:paddingStart="0dp"> @@ -83,10 +82,9 @@ <com.android.systemui.qs.QuickQSPanel android:id="@+id/quick_qs_panel" android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_height="48dp" android:layout_alignParentEnd="true" - android:layout_marginTop="36dp" - android:layout_marginBottom="8dp" + android:layout_marginTop="31dp" android:layout_alignParentTop="true" android:accessibilityTraversalAfter="@+id/date_time_group" android:accessibilityTraversalBefore="@id/expand_indicator" @@ -95,8 +93,7 @@ android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:focusable="true" - android:importantForAccessibility="yes" - android:paddingTop="0dp"/> + android:importantForAccessibility="yes" /> <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/qs_detail_header_progress" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 36ceff57544f..3fce776e2e11 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minute"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minute"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 uur"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ONTDOEN"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Sluimer vir <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Batterygebruik"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index f9edd7c7b54f..a217d3cd8ee9 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ደቂቃዎች"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 ደቂቃዎች"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ሰዓት"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ቀልብስ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"ለ<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> አሸልቧል"</string> <string name="battery_panel_title" msgid="7944156115535366613">"የባትሪ አጠቃቀም"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 4ab49a026a91..1c1fbbce444c 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -589,6 +589,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"١٥ دقيقة"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"٣۰ دقيقة"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"ساعة واحدة"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"تراجع"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"تم تأجيل الإشعار لمدة <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"استخدام البطارية"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index aca6a3b31e07..24b71e7d5515 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 dəqiqə"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 dəqiqə"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 saat"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"GERİ QAYTARIN"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> üçün təxirə salınıb"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Batareya istifadəsi"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 29a5e194c472..f4607300ce5d 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -577,6 +577,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"OPOZOVI"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Odloženo je za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 15f1d86db22a..dfad96ca84e1 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -583,6 +583,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 хвілін"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 хвілін"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 гадзіна"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"АДРАБІЦЬ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Адкладзена на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Выкарыстанне зараду"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index b77cc9e5b3ea..be327135046e 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минути"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 минути"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 час"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ОТМЯНА"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Отложено за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Ползв. на батерията"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index b9fa325880d7..822652ba8ad1 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"১৫ মিনিট"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"৩০ মিনিট"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"১ ঘণ্টা"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"পূর্বাবস্থায় ফিরুন"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> পরে আবার মনে করানো হবে"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ব্যাটারির ব্যবহার"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 11450ae820cc..e4e02d7410d9 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -579,6 +579,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"OPOZOVI"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Odgođeno za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 16f2a32185f5..c9254ef85cf3 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuts"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuts"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"DESFÉS"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"S\'ha posposat <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Ús de la bateria"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index f4a45c2f2645..2ad9dbaa28b3 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -583,6 +583,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minut"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minut"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hodina"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"VRÁTIT ZPĚT"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Odloženo o <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Využití baterie"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 55b39d56dfe4..e2852dd4bada 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutter"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutter"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 time"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"FORTRYD"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Udsat i <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Batteriforbrug"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index bc7f1d5ffb60..b0b4323593ab 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 Minuten"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 Minuten"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 Stunde"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"RÜCKGÄNGIG"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Erinnerung in <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Akkunutzung"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index bbefef459a7d..5d8703492bb2 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 λεπτά"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 λεπτά"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ώρα"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ΑΝΑΙΡΕΣΗ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Σε αφύπνιση για <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Χρήση της μπαταρίας"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 2561d29ecb76..05c413091c1f 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hour"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"UNDO"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozed for <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 2561d29ecb76..05c413091c1f 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hour"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"UNDO"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozed for <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 2561d29ecb76..05c413091c1f 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hour"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"UNDO"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozed for <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 64a4bfebed4f..07b564d9e8ee 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"DESHACER"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Posponer <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 8d9f8a58f853..3bf6a8cc003a 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"DESHACER"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Volverá a mostrarse en <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 604d266623aa..26b460319789 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutit"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutit"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"Üks tund"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"VÕTA TAGASI"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Edasi lükatud <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Akukasutus"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 2c83e5b8ff62..86fd3b24efa5 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutu"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutu"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ordu"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"DESEGIN"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>z atzeratu da"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Bateriaren erabilera"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 1f49e9894262..5570f9edf7de 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"۱۵ دقیقه"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"۳۰ دقیقه"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"۱ ساعت"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"واگرد"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> به تعویق افتاد"</string> <string name="battery_panel_title" msgid="7944156115535366613">"مصرف باتری"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index f5b0b6b96f8e..c60c4c45aa55 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuuttia"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuuttia"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 tunti"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"KUMOA"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Torkku: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Akun käyttö"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index e615ff427574..10b0cba8a0a5 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 heure"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ANNULER"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Reporté pour <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Utilisation de la pile"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 811b16ce37bf..862d13fb748b 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 heure"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ANNULER"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Répétée après <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Utilisation batterie"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 7481d1aea66d..0cb91b454b21 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"DESFACER"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Adiouse <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Uso de batería"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index ca7a779e7f1c..7f718d98b1f6 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 મિનિટ"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 મિનિટ"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 કલાક"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"પૂર્વવત્ કરો"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> માટે સ્નૂઝ કરો"</string> <string name="battery_panel_title" msgid="7944156115535366613">"બૅટરી વપરાશ"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 92bc82e033d0..613d8d302eb7 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनट"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनट"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 घंटा"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"पहले जैसा करें"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> के लिए याद दिलाया गया"</string> <string name="battery_panel_title" msgid="7944156115535366613">"बैटरी उपयोग"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 2065b8c42101..e716f5dfa98d 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -577,6 +577,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"PONIŠTI"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Odgođeno <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index d1e85d91710c..fe1b12b19b54 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 perc"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 perc"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 óra"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"VISSZAVONÁS"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Elhalasztva: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Akkumulátorhasználat"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 1189b0535af6..bdceafe86670 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 րոպե"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 րոպե"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ժամ"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ՀԵՏԱՐԿԵԼ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Հետաձգվել է <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ով"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Մարտկոցի օգտագործում"</string> diff --git a/packages/SystemUI/res/values-hy/strings_tv.xml b/packages/SystemUI/res/values-hy/strings_tv.xml index ac7711b39ecc..0493584e39a7 100644 --- a/packages/SystemUI/res/values-hy/strings_tv.xml +++ b/packages/SystemUI/res/values-hy/strings_tv.xml @@ -19,7 +19,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="notification_channel_tv_pip" msgid="134047986446577723">"Նկարը նկարի մեջ"</string> + <string name="notification_channel_tv_pip" msgid="134047986446577723">"Նկար նկարի մեջ"</string> <string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Առանց վերնագրի ծրագիր)"</string> <string name="pip_close" msgid="3480680679023423574">"Փակել PIP-ն"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Լիէկրան"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 25a2a14b0afa..2853d9d291dd 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 menit"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 menit"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 jam"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"URUNG"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Ditunda selama <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Pemakaian baterai"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index d2b97872344f..f56720ae1d35 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 mínútur"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 mínútur"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 klukkustund"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"AFTURKALLA"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Þaggað í <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Rafhlöðunotkun"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 01b2464ed938..cfe5deb3e6e5 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuti"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuti"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ora"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ANNULLA"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Posticipato di <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Utilizzo batteria"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index b7e950819f02..4b1236e5758b 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -581,6 +581,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 דקות"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 דקות"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"שעה אחת"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ביטול"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"נדחה לטיפול בעוד <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"שימוש בסוללה"</string> @@ -638,7 +640,7 @@ <string name="headset" msgid="4534219457597457353">"אוזניות"</string> <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"אוזניות מחוברות"</string> <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"אוזניות מחוברות"</string> - <string name="data_saver" msgid="5037565123367048522">"חוסך הנתונים<br>(Data Saver)"</string> + <string name="data_saver" msgid="5037565123367048522">"חוסך הנתונים (Data Saver)"</string> <string name="accessibility_data_saver_on" msgid="8454111686783887148">"חוסך הנתונים (Data Saver) פועל"</string> <string name="accessibility_data_saver_off" msgid="8841582529453005337">"חוסך הנתונים (Data Saver) כבוי"</string> <string name="switch_bar_on" msgid="1142437840752794229">"פועל"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 15fccc618d4e..4c7c85e43570 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15分"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30分"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1時間"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"元に戻す"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"スヌーズ: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"電池の使用状況"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 17320ef7eaf0..d8cbc199ad5b 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 წუთი"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 წუთი"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 საათი"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"მოქმედების გაუქმება"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"ჩაჩუმებული იქნება <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ბატარეის მოხმარება"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 724af886ebce..f71601eb9b21 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минут"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 минут"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 сағат"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"КЕРІ ҚАЙТАРУ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> кідіртілді"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Батареяны пайдалану"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 229e345f82ed..9aed68928016 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 នាទី"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 នាទី"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ម៉ោង"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"មិនធ្វើវិញ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"បានផ្អាករយៈពេល <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ការប្រើប្រាស់ថ្ម"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 9c87cf7fd0bd..cd85f749d288 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ನಿಮಿಷಗಳು"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 ನಿಮಿಷಗಳು"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ಗಂಟೆ"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ರದ್ದುಮಾಡಿ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ಗೆ ಸ್ನೂಜ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ಬ್ಯಾಟರಿ ಬಳಕೆ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 273b39051fcb..a237ba9926b7 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15분"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30분"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1시간"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"실행취소"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> 동안 일시 중지됨"</string> <string name="battery_panel_title" msgid="7944156115535366613">"배터리 사용량"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 209d38d80263..1127c24c0b10 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 мүнөт"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 мүнөт"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 саат"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"КАЙТАРУУ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> тындырылды"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Батарея колдонулушу"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 536958370d53..42baec6d95ca 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ນາທີ"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 ນາທີ"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ຊົ່ວໂມງ"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ຍົກເລີກ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"ເລື່ອນໄປ <xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ນາທີແລ້ວ"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ການໃຊ້ແບັດເຕີຣີ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index cc123cf179d9..ce403ef8c6cb 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -581,6 +581,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 min."</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 min."</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 val."</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ANULIUOTI"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Nustatyta snausti <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Akum. energ. vartoj."</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 9bd3c65bf260..28758ca7609b 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -577,6 +577,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minūtes"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minūtes"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 stunda"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ATSAUKT"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Atlikts: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Akumulatora lietojums"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 519cfac30323..3355090c121f 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минути"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 минути"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 час"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ВРАТИ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Одложено за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Користење батерија"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index a7aa20a401e0..a41e305eea55 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 മിനിറ്റ്"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 മിനിറ്റ്"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"ഒരു മണിക്കൂർ"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"പഴയപടിയാക്കുക"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> സമയത്തേക്ക് സ്നൂസ് ചെയ്തു"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ബാറ്ററി ഉപയോഗം"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 7144c2849406..3a33cd6cb01f 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минут"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 минут"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 цаг"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"БУЦААХ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>-д түр хойшлуулсан"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Тэжээл ашиглалт"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index f7360c9d6944..ad107d8390f2 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनिटे"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनिटे"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 तास"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"पूर्ववत करा"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> साठी स्नूझ करा"</string> <string name="battery_panel_title" msgid="7944156115535366613">"बॅटरी वापर"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index a05dd2b4984c..898cdfc849f2 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minit"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minit"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 jam"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"BUAT ASAL"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Ditunda selama <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Penggunaan bateri"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 797aa977c8d5..346bbe245e32 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"၁၅ မိနစ်"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"၃၀ မိနစ်"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"၁ နာရီ"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"တစ်ဆင့် နောက်ပြန်ပြန်ပါ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ဆိုင်းငံ့ရန်"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ဘက်ထရီ အသုံးပြုမှု"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index f59367fcedaa..a13c09745958 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutter"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutter"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 time"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ANGRE"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Slumrer i <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Batteribruk"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index fb49b17bee2a..c8cd38384b7b 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"१५ मिनेट"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"३० मिनेट"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"१ घन्टा"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"अनडू गर्नुहोस्"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> का लागि स्नुज गरियो"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ब्याट्री उपयोग"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index b708e6631789..78077e973050 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuten"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuten"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 uur"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ONGEDAAN MAKEN"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozefunctie <xliff:g id="TIME_AMOUNT">%1$s</xliff:g> actief"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Accugebruik"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 1039e3407678..07a0e8222e07 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ਮਿੰਟ"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 ਮਿੰਟ"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ਘੰਟਾ"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ਅਣਕੀਤਾ ਕਰੋ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ਲਈ ਸਨੂਜ਼ ਕੀਤਾ ਗਿਆ"</string> <string name="battery_panel_title" msgid="7944156115535366613">"ਬੈਟਰੀ ਵਰਤੋਂ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 91a7c09c5752..03b5ed9e9acd 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -581,6 +581,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 min"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 min"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 godz."</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"COFNIJ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Odłożono na <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Wykorzystanie baterii"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index ab705e7f58fb..8ef330b7a447 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"Uma hora"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"DESFAZER"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Adiada para <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 74089b2982cf..49f14804ea58 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -444,29 +444,29 @@ <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"A sua entidade instalou uma autoridade de certificação no seu perfil de trabalho. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string> <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"Está instalada uma autoridade de certificação neste dispositivo. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string> <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"O administrador ativou os registos de rede, que monitorizam o tráfego no seu dispositivo."</string> - <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string> - <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"Está ligado às redes <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que podem monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string> - <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"O seu perfil de trabalho está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string> - <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"O seu perfil pessoal está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string> + <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string> + <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"Está ligado às redes <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que podem monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string> + <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"O seu perfil de trabalho está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string> + <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"O seu perfil pessoal está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string> <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"O seu dispositivo é gerido pelo <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string> <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"A <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> utiliza o <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> para gerir o seu dispositivo."</string> <string name="monitoring_description_do_body" msgid="3639594537660975895">"O administ. pode monitorizar e gerir definições, acesso empresarial, aplic. e dados associados ao dispositivo, bem como inf. de localiz. do disp."</string> <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string> <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saiba mais"</string> - <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string> + <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Abrir as definições de VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Abrir credenciais fidedignas"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"O seu administrador ativou os registos de rede, que monitorizam o tráfego no seu dispositivo.\n\nPara obter mais informações, contacte o administrador."</string> - <string name="monitoring_description_vpn" msgid="4445150119515393526">"Concedeu autorização a uma aplicação para configurar uma ligação VPN.\n\nEsta aplicação pode monitorizar a atividade do dispositivo e da rede, incluindo emails, aplicações e Websites."</string> - <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu administrador tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Websites.\n\nPara obter mais informações, contacte o administrador.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string> + <string name="monitoring_description_vpn" msgid="4445150119515393526">"Concedeu autorização a uma aplicação para configurar uma ligação VPN.\n\nEsta aplicação pode monitorizar a atividade do dispositivo e da rede, incluindo emails, aplicações e Sites."</string> + <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu administrador tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Sites.\n\nPara obter mais informações, contacte o administrador.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string> <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string> - <string name="monitoring_description_app" msgid="1828472472674709532">"Está associado à aplicação <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string> - <string name="monitoring_description_app_personal" msgid="484599052118316268">"Está ligado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Websites."</string> - <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Está ligado ao <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Websites."</string> - <string name="monitoring_description_app_work" msgid="4612997849787922906">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Websites.\n\nContacte o administrador para obter mais informações."</string> - <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Websites.\n\nTambém está associado à aplicação <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorizar a atividade da rede pessoal."</string> + <string name="monitoring_description_app" msgid="1828472472674709532">"Está associado à aplicação <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string> + <string name="monitoring_description_app_personal" msgid="484599052118316268">"Está ligado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Sites."</string> + <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Está ligado ao <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Sites."</string> + <string name="monitoring_description_app_work" msgid="4612997849787922906">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Sites.\n\nContacte o administrador para obter mais informações."</string> + <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Sites.\n\nTambém está associado à aplicação <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorizar a atividade da rede pessoal."</string> <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até ser desbloqueado manualmente"</string> <string name="hidden_notifications_title" msgid="7139628534207443290">"Receber notificações mais rapidamente"</string> <string name="hidden_notifications_text" msgid="2326409389088668981">"Ver antes de desbloquear"</string> @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ANULAR"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Suspensa por <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Utiliz. da bateria"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index ab705e7f58fb..8ef330b7a447 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"Uma hora"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"DESFAZER"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Adiada para <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index cadce25ee1ec..29bc5bf22584 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -579,6 +579,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minute"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 de minute"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 oră"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ANULAȚI"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Amânată <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Utilizarea bateriei"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 34939b58fec4..e593f89d6961 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -583,6 +583,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минут"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 минут"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 час"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ОТМЕНИТЬ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Отложено на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Уровень заряда"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 7065c83b8aa2..991be52d2a14 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"මිනිත්තු 15"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"මිනිත්තු 30"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"පැය 1"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"අස් කරන්න"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ක් මදක් නතර කරන ලදී"</string> <string name="battery_panel_title" msgid="7944156115535366613">"බැටරි භාවිතය"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 6e4c33bb3b1e..33793ce7795f 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -583,6 +583,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minút"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minút"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hod."</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"SPÄŤ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Stlmené na <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Využitie batérie"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index b0e770fbdd6c..9e03e425dcd4 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -583,6 +583,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minut"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minut"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ura"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"RAZVELJAVI"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Preloženo za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Poraba akumulatorja"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index a68ec872ebb7..cbdb5b21ddbe 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 orë"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ZHBËJ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"U shty për <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Përdorimi i baterisë"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index f4b488422d66..5c4790762b00 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -577,6 +577,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минута"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 минута"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 сат"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ОПОЗОВИ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Одложено је за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Потрошња батерије"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 685c0a445a83..967e3a5a4aa0 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuter"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuter"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 timme"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ÅNGRA"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozad i <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Batteriförbrukning"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 9a52d9b1e39e..82220748a875 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"Dakika 15"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"Dakika 30"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"Saa 1"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"TENDUA"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Imeahirishwa kwa <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Matumizi ya betri"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 1c4b7de301f2..eb672e18e30e 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 நிமிடங்கள்"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 நிமிடங்கள்"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 மணிநேரம்"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"செயல்தவிர்"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"உறக்கநிலையில் வைத்திருந்த நேரம்: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"பேட்டரி உபயோகம்"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 2bdabd2bcc83..b5470e75101f 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 నిమిషాలు"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 నిమిషాలు"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 గంట"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"చర్య రద్దు చేయి"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> వరకు తాత్కాలికంగా ఆపివేయబడింది"</string> <string name="battery_panel_title" msgid="7944156115535366613">"బ్యాటరీ వినియోగం"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 8077d1432642..f47cfa9b6b7f 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -64,7 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"ลายนิ้วมือหลัก RSA ของคอมพิวเตอร์คือ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"อนุญาตจากคอมพิวเตอร์เครื่องนี้เสมอ"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"ไม่อนุญาตให้แก้ไขข้อบกพร่องผ่าน USB"</string> - <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"ผู้ใช้ที่ลงชื่อเข้าใช้อุปกรณ์นี้อยู่ในขณะนี้ไม่สามารถเปิดการแก้ปัญหาผ่าน USB ได้ หากต้องการใช้คุณลักษณะนี้ โปรดเปลี่ยนไปเป็นผู้ใช้ที่เป็นผู้ดูแลระบบ"</string> + <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"ผู้ใช้ที่ลงชื่อเข้าใช้อุปกรณ์นี้อยู่ในขณะนี้ไม่สามารถเปิดการแก้ปัญหาผ่าน USB ได้ หากต้องการใช้ฟีเจอร์นี้ โปรดเปลี่ยนไปเป็นผู้ใช้ที่เป็นผู้ดูแลระบบ"</string> <string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string> <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"กำลังบันทึกภาพหน้าจอ..."</string> @@ -524,12 +524,12 @@ <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"ฮอตสปอต"</string> <string name="accessibility_managed_profile" msgid="6613641363112584120">"โปรไฟล์งาน"</string> <string name="tuner_warning_title" msgid="7094689930793031682">"เพลิดเพลินกับบางส่วนแต่ไม่ใช่ทั้งหมด"</string> - <string name="tuner_warning" msgid="8730648121973575701">"ตัวรับสัญญาณ UI ระบบช่วยให้คุณมีวิธีพิเศษในการปรับแต่งและกำหนดค่าส่วนติดต่อผู้ใช้ Android คุณลักษณะรุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string> - <string name="tuner_persistent_warning" msgid="8597333795565621795">"คุณลักษณะรุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string> + <string name="tuner_warning" msgid="8730648121973575701">"ตัวรับสัญญาณ UI ระบบช่วยให้คุณมีวิธีพิเศษในการปรับแต่งและกำหนดค่าส่วนติดต่อผู้ใช้ Android ฟีเจอร์รุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string> + <string name="tuner_persistent_warning" msgid="8597333795565621795">"ฟีเจอร์รุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string> <string name="got_it" msgid="2239653834387972602">"รับทราบ"</string> <string name="tuner_toast" msgid="603429811084428439">"ยินดีด้วย! เพิ่มตัวรับสัญญาณ UI ระบบไปยังการตั้งค่าแล้ว"</string> <string name="remove_from_settings" msgid="8389591916603406378">"นำออกจากการตั้งค่า"</string> - <string name="remove_from_settings_prompt" msgid="6069085993355887748">"นำตัวรับสัญญาณ UI ระบบออกจากการตั้งค่าและหยุดใช้คุณลักษณะทั้งหมดของตัวรับสัญญาณใช่ไหม"</string> + <string name="remove_from_settings_prompt" msgid="6069085993355887748">"นำตัวรับสัญญาณ UI ระบบออกจากการตั้งค่าและหยุดใช้ฟีเจอร์ทั้งหมดของตัวรับสัญญาณใช่ไหม"</string> <string name="activity_not_found" msgid="348423244327799974">"ยังไม่ได้ติดตั้งแอปพลิเคชันบนอุปกรณ์ของคุณ"</string> <string name="clock_seconds" msgid="7689554147579179507">"แสดงวินาทีของนาฬิกา"</string> <string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string> @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 นาที"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 นาที"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ชั่วโมง"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"เลิกทำ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"ปิดเสียงเตือนชั่วคราวไว้เป็นเวลา <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"การใช้งานแบตเตอรี่"</string> @@ -719,7 +721,7 @@ <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ลากลงเพื่อปิด"</string> <string name="pip_menu_title" msgid="3328510504196964712">"เมนูการแสดงผลหลายแหล่งพร้อมกัน"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ใช้การแสดงผลหลายแหล่งพร้อมกัน"</string> - <string name="pip_notification_message" msgid="4171698133469539591">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้คุณลักษณะนี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดคุณลักษณะ"</string> + <string name="pip_notification_message" msgid="4171698133469539591">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้ฟีเจอร์นี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดฟีเจอร์"</string> <string name="pip_play" msgid="1417176722760265888">"เล่น"</string> <string name="pip_pause" msgid="8881063404466476571">"หยุดชั่วคราว"</string> <string name="pip_skip_to_next" msgid="1948440006726306284">"ข้ามไปรายการถัดไป"</string> @@ -728,7 +730,7 @@ <string name="thermal_shutdown_message" msgid="9006456746902370523">"ขณะนี้โทรศัพท์ทำงานเป็นปกติ"</string> <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"โทรศัพท์ร้อนเกินไปจึงปิดเครื่องเพื่อให้เย็นลง ขณะนี้โทรศัพท์ทำงานเป็นปกติ\n\nโทรศัพท์อาจร้อนเกินไปหากคุณ\n • ใช้แอปที่ใช้ทรัพยากรมาก (เช่น เกม วิดีโอ หรือแอปการนำทาง)\n • ดาวน์โหลดหรืออัปโหลดไฟล์ขนาดใหญ่\n • ใช้โทรศัพท์ในอุณหภูมิที่สูง"</string> <string name="high_temp_title" msgid="4589508026407318374">"โทรศัพท์เริ่มเครื่องร้อน"</string> - <string name="high_temp_notif_message" msgid="5642466103153429279">"คุณลักษณะบางอย่างจะใช้งานได้จำกัดขณะโทรศัพท์ลดอุณหภูมิลง"</string> + <string name="high_temp_notif_message" msgid="5642466103153429279">"ฟีเจอร์บางอย่างจะใช้งานได้จำกัดขณะโทรศัพท์ลดอุณหภูมิลง"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"โทรศัพท์จะพยายามลดอุณหภูมิลงโดยอัตโนมัติ คุณยังสามารถใช้โทรศัพท์ได้ แต่โทรศัพท์อาจทำงานช้าลง\n\nโทรศัพท์จะทำงานตามปกติเมื่อเย็นลงแล้ว"</string> <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ทางลัดทางซ้าย"</string> <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"ทางลัดทางขวา"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 194b16186de6..3304ab71c7ac 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuto"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuto"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 oras"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"I-UNDO"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Na-snooze ng <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Paggamit ng baterya"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 7f1d8ff71d68..944316cc7d77 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 dakika"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 dakika"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 saat"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"GERİ AL"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> süreyle ertelendi"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Pil kullanımı"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 1006eae3a18d..5636a8725fc6 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -583,6 +583,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 хвилин"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 хвилин"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 годину"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"ВІДМІНИТИ"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Відкладено на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Використання заряду"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 9f284942c011..7a5f1c7fba7b 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 منٹ"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 منٹ"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 گھنٹہ"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"کالعدم کریں"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> کیلئے اسنوز کیا گیا"</string> <string name="battery_panel_title" msgid="7944156115535366613">"بیٹری کا استعمال"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 02f7c43b4045..262225c10761 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -201,7 +201,7 @@ <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Parvoz rejimi o‘chirildi."</string> <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Parvoz rejimi yoqildi."</string> <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"“Bezovta qilinmasin” funksiyasi yoqilgan, faqat muhim bildirishnomalar ko‘rsatiladi."</string> - <string name="accessibility_quick_settings_dnd_none_on" msgid="6882582132662613537">"Bezovta qilinmasin, tinchlik saqlansin"</string> + <string name="accessibility_quick_settings_dnd_none_on" msgid="6882582132662613537">"Bezovta qilinmasin, jimjitlik."</string> <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Bezovta qilinmasin, faqat signallar"</string> <string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"Bezovta qilinmasin."</string> <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"“Bezovta qilinmasin” funksiyasi o‘chirilgan."</string> @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 daqiqa"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 daqiqa"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 soat"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"BEKOR QILISH"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> muddatga kechiktirildi"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Batareya sarfi"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 167d0a1eeed0..1d125f6d9336 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 phút"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 phút"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 giờ"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"HOÀN TÁC"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Báo lại sau <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Mức sử dụng pin"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index cf9b7d2b421c..600e17d4d029 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 分钟"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 分钟"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 小时"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"撤消"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"已延后 <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"电池使用情况"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index d123c930c2ca..109c33e93572 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -575,6 +575,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 分鐘"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 分鐘"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 小時"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"復原"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"已延後 <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index af7ed48ca93f..353d98590243 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -268,7 +268,7 @@ <string name="ethernet_label" msgid="7967563676324087464">"乙太網路"</string> <string name="quick_settings_dnd_label" msgid="8735855737575028208">"零打擾"</string> <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"僅限優先通知"</string> - <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"僅允許鬧鐘"</string> + <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"僅限鬧鐘"</string> <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"完全靜音"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 個裝置)"</string> @@ -369,7 +369,7 @@ <string name="interruption_level_none_with_warning" msgid="5114872171614161084">"完全靜音。這也會關閉螢幕閱讀器的音訊。"</string> <string name="interruption_level_none" msgid="6000083681244492992">"完全靜音"</string> <string name="interruption_level_priority" msgid="6426766465363855505">"僅限優先通知"</string> - <string name="interruption_level_alarms" msgid="5226306993448328896">"僅允許鬧鐘"</string> + <string name="interruption_level_alarms" msgid="5226306993448328896">"僅限鬧鐘"</string> <string name="interruption_level_none_twoline" msgid="3957581548190765889">"完全\n靜音"</string> <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"僅允許\n優先通知"</string> <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"僅允許\n鬧鐘"</string> @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 分鐘"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 分鐘"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 小時"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"復原"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"已延後 <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index c1765c692520..d81c32084b8e 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -573,6 +573,8 @@ <string name="snooze_option_15_min" msgid="1068727451405610715">"15 amaminithi"</string> <string name="snooze_option_30_min" msgid="867081342535195788">"30 amaminithi"</string> <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ihora"</string> + <!-- no translation found for snooze_option_2_hour (8332218255658969475) --> + <skip /> <string name="snooze_undo" msgid="6074877317002985129">"HLEHLISA"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"Kusnuzwe u-<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <string name="battery_panel_title" msgid="7944156115535366613">"Ukusetshenziswa kwebhethri"</string> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index f0ff22dc45c7..db1e8a9c112e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -147,8 +147,10 @@ public class KeyguardStatusView extends GridLayout { mClockView.setLayoutParams(layoutParams); mDateView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.widget_label_font_size)); - mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX, - getResources().getDimensionPixelSize(R.dimen.widget_label_font_size)); + if (mOwnerInfo != null) { + mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.widget_label_font_size)); + } } public void refreshTime() { diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index c35fdd5c5781..854696ee313d 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -716,9 +716,15 @@ public class PipTouchHandler { * Updates the current movement bounds based on whether the menu is currently visible. */ private void updateMovementBounds(int menuState) { - mMovementBounds = menuState == MENU_STATE_FULL + boolean isMenuExpanded = menuState == MENU_STATE_FULL; + mMovementBounds = isMenuExpanded ? mExpandedMovementBounds : mNormalMovementBounds; + try { + mPinnedStackController.setMinEdgeSize(isMenuExpanded ? mExpandedShortestEdgeSize : 0); + } catch (RemoteException e) { + Log.e(TAG, "Could not set minimized state", e); + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java index 149b5ccd7b1a..0d74b7a85ad1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java @@ -58,6 +58,16 @@ public class QSContainerImpl extends FrameLayout { mBackground = findViewById(R.id.qs_background); mGutterHeight = getContext().getResources().getDimensionPixelSize(R.dimen.qs_gutter_height); mFullElevation = mQSPanel.getElevation(); + + setClickable(true); + setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); + } + + @Override + public boolean performClick() { + // Want to receive clicks so missing QQS tiles doesn't cause collapse, but + // don't want to do anything with them. + return true; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java index 87b042d61147..682c56c0ef24 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java @@ -101,6 +101,8 @@ public class QSFooter extends FrameLayout implements private boolean mShowEditIcon; private TouchAnimator mAnimator; private View mDateTimeGroup; + private boolean mKeyguardShowing; + private TouchAnimator mAlarmAnimator; public QSFooter(Context context, AttributeSet attrs) { super(context, attrs); @@ -163,13 +165,14 @@ public class QSFooter extends FrameLayout implements int remaining = (width - numTiles * size) / (numTiles - 1); int defSpace = mContext.getResources().getDimensionPixelOffset(R.dimen.default_gear_space); - final Builder builder = new Builder() + mAnimator = new Builder() .addFloat(mSettingsContainer, "translationX", -(remaining - defSpace), 0) .addFloat(mSettingsButton, "rotation", -120, 0) - .addFloat(mAlarmStatus, "alpha", 0, 1); + .build(); if (mAlarmShowing) { - builder.addFloat(mDate, "alpha", 1, 0) + mAlarmAnimator = new Builder().addFloat(mDate, "alpha", 1, 0) .addFloat(mDateTimeGroup, "translationX", 0, -mDate.getWidth()) + .addFloat(mAlarmStatus, "alpha", 0, 1) .setListener(new ListenerAdapter() { @Override public void onAnimationAtStart() { @@ -180,13 +183,13 @@ public class QSFooter extends FrameLayout implements public void onAnimationStarted() { mAlarmStatus.setVisibility(View.VISIBLE); } - }); + }).build(); } else { + mAlarmAnimator = null; mAlarmStatus.setVisibility(View.GONE); mDate.setAlpha(1); mDateTimeGroup.setTranslationX(0); } - mAnimator = builder.build(); setExpansion(mExpansionAmount); } @@ -248,6 +251,11 @@ public class QSFooter extends FrameLayout implements return animatorBuilder.build(); } + public void setKeyguardShowing(boolean keyguardShowing) { + mKeyguardShowing = keyguardShowing; + setExpansion(mExpansionAmount); + } + public void setExpanded(boolean expanded) { if (mExpanded == expanded) return; mExpanded = expanded; @@ -275,6 +283,8 @@ public class QSFooter extends FrameLayout implements public void setExpansion(float headerExpansionFraction) { mExpansionAmount = headerExpansionFraction; if (mAnimator != null) mAnimator.setPosition(headerExpansionFraction); + if (mAlarmAnimator != null) mAlarmAnimator.setPosition( + mKeyguardShowing ? 0 : headerExpansionFraction); if (mSettingsAlpha != null) { mSettingsAlpha.setPosition(headerExpansionFraction); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 61fd6244b700..c9c3a7f9e147 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -222,6 +222,7 @@ public class QSFragment extends Fragment implements QS { mQSAnimator.setOnKeyguard(keyguardShowing); } + mFooter.setKeyguardShowing(keyguardShowing); updateQsState(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index 8539cb9d5473..00b883a541db 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -60,6 +60,12 @@ public class QuickQSPanel extends QSPanel { mTileLayout = new HeaderTileLayout(context); mTileLayout.setListening(mListening); addView((View) mTileLayout, 0 /* Between brightness and footer */); + super.setPadding(0, 0, 0, 0); + } + + @Override + public void setPadding(int left, int top, int right, int bottom) { + // Always have no padding. } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index e457d7247434..abafd64e3707 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -23,13 +23,11 @@ import android.support.annotation.VisibleForTesting; import android.util.AttributeSet; import android.view.View; import android.widget.RelativeLayout; -import android.widget.TextClock; import com.android.settingslib.Utils; import com.android.systemui.BatteryMeterView; import com.android.systemui.Dependency; import com.android.systemui.R; -import com.android.systemui.R.id; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.qs.QSDetail.Callback; import com.android.systemui.statusbar.SignalClusterView; @@ -79,7 +77,7 @@ public class QuickStatusBarHeader extends RelativeLayout { battery.setForceShowPercent(true); // Don't show the Wi-Fi indicator here, because it is shown just below in the tile. SignalClusterView signalCluster = findViewById(R.id.signal_cluster); - signalCluster.setForceBlockWifi(); + signalCluster.setQsSignalCluster(); mActivityStarter = Dependency.get(ActivityStarter.class); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 1afce64539d2..76f6e7d7d243 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -353,13 +353,20 @@ public class WifiTile extends QSTileImpl<SignalState> { private void updateItems() { if (mItems == null) return; - if (mSignalCallback.mInfo.enabled) { - mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty, - R.string.quick_settings_wifi_detail_empty_text); - } else { + + // Wi-Fi is off + if (!mSignalCallback.mInfo.enabled) { mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty, R.string.wifi_is_off); + mItems.setItems(null); + return; } + + // No available access points + mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty, + R.string.quick_settings_wifi_detail_empty_text); + + // Build the list Item[] items = null; if (mAccessPoints != null) { items = new Item[mAccessPoints.length]; diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index e2e9b1b7d76f..611169f575c1 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -30,6 +30,7 @@ import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.GraphicBuffer; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; @@ -239,8 +240,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } }); - protected Bitmap mThumbTransitionBitmapCache; - public RecentsImpl(Context context) { mContext = context; mHandler = new Handler(); @@ -775,14 +774,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight); } - - // Update the transition bitmap to match the new header bar height - if (mThumbTransitionBitmapCache == null || - (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) || - (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) { - mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth, - mTaskBarHeight, Bitmap.Config.ARGB_8888); - } } } @@ -864,8 +855,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task, stackScroller.getStackScroll(), mTmpTransform, null, windowOverrideRect); - Bitmap thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform, - mThumbTransitionBitmapCache); + GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform); Rect toTaskRect = new Rect(); mTmpTransform.rect.round(toTaskRect); specs.add(new AppTransitionAnimationSpec(task.key.id, thumbnail, toTaskRect)); @@ -887,8 +877,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener () -> { Rect rect = new Rect(); toTaskRect.round(rect); - Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform, - mThumbTransitionBitmapCache); + GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(toTask, + toTransform); return Lists.newArrayList(new AppTransitionAnimationSpec( toTask.key.id, thumbnail, rect)); }); @@ -924,19 +914,19 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener /** * Draws the header of a task used for the window animation into a bitmap. */ - private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform, - Bitmap thumbnail) { + private GraphicBuffer drawThumbnailTransitionBitmap(Task toTask, + TaskViewTransform toTransform) { SystemServicesProxy ssp = Recents.getSystemServices(); if (toTransform != null && toTask.key != null) { synchronized (mHeaderBarLock) { boolean disabledInSafeMode = !toTask.isSystemApp && ssp.isInSafeMode(); - mHeaderBar.onTaskViewSizeChanged((int) toTransform.rect.width(), - (int) toTransform.rect.height()); + int width = (int) toTransform.rect.width(); + int height = (int) toTransform.rect.height(); + mHeaderBar.onTaskViewSizeChanged(width, height); if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { - thumbnail.eraseColor(0xFFff0000); + return RecentsTransitionHelper.drawViewIntoGraphicBuffer(width, mTaskBarHeight, + null, 1f, 0xFFff0000); } else { - thumbnail.eraseColor(0); - Canvas c = new Canvas(thumbnail); // Workaround for b/27815919, reset the callback so that we do not trigger an // invalidate on the header bar as a result of updating the icon Drawable icon = mHeaderBar.getIconView().getDrawable(); @@ -947,11 +937,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener disabledInSafeMode); mHeaderBar.onTaskDataLoaded(); mHeaderBar.setDimAlpha(toTransform.dimAlpha); - mHeaderBar.draw(c); - c.setBitmap(null); + return RecentsTransitionHelper.drawViewIntoGraphicBuffer(width, mTaskBarHeight, + mHeaderBar, 1f, 0); } } - return thumbnail.createAshmemBitmap(); } return null; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java index d7d264e3aa07..21dfe8caf964 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java @@ -30,6 +30,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.GraphicBuffer; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; @@ -37,7 +38,11 @@ import android.os.IRemoteCallback; import android.os.RemoteException; import android.util.Log; import android.view.AppTransitionAnimationSpec; +import android.view.DisplayListCanvas; import android.view.IAppTransitionAnimationSpecsFuture; +import android.view.RenderNode; +import android.view.ThreadedRenderer; +import android.view.View; import com.android.internal.annotations.GuardedBy; import com.android.systemui.recents.Recents; @@ -264,8 +269,8 @@ public class RecentsTransitionHelper { Rect bounds) { mTmpTransform.fillIn(taskView); Task task = taskView.getTask(); - Bitmap thumbnail = RecentsTransitionHelper.composeTaskBitmap(taskView, mTmpTransform); - return Collections.singletonList(new AppTransitionAnimationSpec(task.key.id, thumbnail, + GraphicBuffer buffer = RecentsTransitionHelper.composeTaskBitmap(taskView, mTmpTransform); + return Collections.singletonList(new AppTransitionAnimationSpec(task.key.id, buffer, bounds)); } @@ -346,7 +351,7 @@ public class RecentsTransitionHelper { return new AppTransitionAnimationSpec(task.key.id, null, taskRect); } - public static Bitmap composeTaskBitmap(TaskView taskView, TaskViewTransform transform) { + public static GraphicBuffer composeTaskBitmap(TaskView taskView, TaskViewTransform transform) { float scale = transform.scale; int fromWidth = (int) (transform.rect.width() * scale); int fromHeight = (int) (transform.rect.height() * scale); @@ -354,26 +359,17 @@ public class RecentsTransitionHelper { Log.e(TAG, "Could not compose thumbnail for task: " + taskView.getTask() + " at transform: " + transform); - Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); - b.eraseColor(Color.TRANSPARENT); - return b; + return drawViewIntoGraphicBuffer(1, 1, null, 1f, 0x00ffffff); } else { - Bitmap b = Bitmap.createBitmap(fromWidth, fromHeight, - Bitmap.Config.ARGB_8888); - if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { - b.eraseColor(0xFFff0000); + return drawViewIntoGraphicBuffer(fromWidth, fromHeight, null, 1f, 0xFFff0000); } else { - Canvas c = new Canvas(b); - c.scale(scale, scale); - taskView.draw(c); - c.setBitmap(null); + return drawViewIntoGraphicBuffer(fromWidth, fromHeight, taskView, scale, 0); } - return b.createAshmemBitmap(); } } - private static Bitmap composeHeaderBitmap(TaskView taskView, + private static GraphicBuffer composeHeaderBitmap(TaskView taskView, TaskViewTransform transform) { float scale = transform.scale; int headerWidth = (int) (transform.rect.width()); @@ -382,16 +378,30 @@ public class RecentsTransitionHelper { return null; } - Bitmap b = Bitmap.createBitmap(headerWidth, headerHeight, Bitmap.Config.ARGB_8888); if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { - b.eraseColor(0xFFff0000); + return drawViewIntoGraphicBuffer(headerWidth, headerHeight, null, 1f, 0xFFff0000); } else { - Canvas c = new Canvas(b); - c.scale(scale, scale); - taskView.mHeaderView.draw(c); - c.setBitmap(null); + return drawViewIntoGraphicBuffer(headerWidth, headerHeight, taskView.mHeaderView, + scale, 0); + } + } + + public static GraphicBuffer drawViewIntoGraphicBuffer(int bufferWidth, int bufferHeight, + View view, float scale, int eraseColor) { + RenderNode node = RenderNode.create("RecentsTransition", null); + node.setLeftTopRightBottom(0, 0, bufferWidth, bufferHeight); + node.setClipToBounds(false); + DisplayListCanvas c = node.start(bufferWidth, bufferHeight); + c.scale(scale, scale); + if (eraseColor != 0) { + c.drawColor(eraseColor); + } + if (view != null) { + view.draw(c); } - return b.createAshmemBitmap(); + node.end(c); + return ThreadedRenderer.createHardwareBitmap(node, bufferWidth, bufferHeight) + .createGraphicBufferHandle(); } /** @@ -399,7 +409,7 @@ public class RecentsTransitionHelper { */ private static AppTransitionAnimationSpec composeAnimationSpec(TaskStackView stackView, TaskView taskView, TaskViewTransform transform, boolean addHeaderBitmap) { - Bitmap b = null; + GraphicBuffer b = null; if (addHeaderBitmap) { b = composeHeaderBitmap(taskView, transform); if (b == null) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java index 2180ec824fb6..46619c214f12 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java @@ -138,7 +138,7 @@ public class RecentsViewTouchHandler { } mVisibleDockStates.clear(); - if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask() + if (ActivityManager.supportsMultiWindow(mRv.getContext()) && !ssp.hasDockedTask() && mDividerSnapAlgorithm.isSplitScreenFeasible()) { Recents.logDockAttempt(mRv.getContext(), event.task.getTopComponent(), event.task.resizeMode); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java index 2c3e78f8cb84..0c6b6b842655 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java @@ -59,7 +59,7 @@ public class TaskViewAccessibilityDelegate extends View.AccessibilityDelegate { @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); - if (ActivityManager.supportsSplitScreenMultiWindow() + if (ActivityManager.supportsSplitScreenMultiWindow(mTaskView.getContext()) && !Recents.getSystemServices().hasDockedTask()) { TaskStack.DockState[] dockStates = Recents.getConfiguration() .getDockStatesForCurrentOrientation(); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index d01bba86636f..9e2ec571faa8 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -832,7 +832,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, .setDuration(animDuration) .start(); mAdjustedForIme = adjustedForIme; - if (mHomeStackResizable && adjustedForIme) { + + // Only get new position if home stack is resizable, ime is open and not minimized + // (including the animation) + if (mHomeStackResizable && adjustedForIme && !mIsInMinimizeInteraction) { mDividerPositionBeforeMinimized = getCurrentPosition(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index 28a858c066ce..ab41485793a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -121,6 +121,7 @@ public class SignalClusterView extends LinearLayout implements NetworkController private boolean mBlockEthernet; private boolean mActivityEnabled; private boolean mForceBlockWifi; + private boolean mQsSignal; public SignalClusterView(Context context) { this(context, null); @@ -152,9 +153,10 @@ public class SignalClusterView extends LinearLayout implements NetworkController updateActivityEnabled(); } - public void setForceBlockWifi() { + public void setQsSignalCluster() { mForceBlockWifi = true; mBlockWifi = true; + mQsSignal = true; if (isAttachedToWindow()) { // Re-register to get new callbacks. mNetworkController.removeCallback(this); @@ -292,26 +294,30 @@ public class SignalClusterView extends LinearLayout implements NetworkController mWifiStrengthId = statusIcon.icon; mWifiBadgeId = statusIcon.iconOverlay; mWifiDescription = statusIcon.contentDescription; - mWifiIn = activityIn && mActivityEnabled; - mWifiOut = activityOut && mActivityEnabled; + mWifiIn = activityIn && mActivityEnabled && mWifiVisible; + mWifiOut = activityOut && mActivityEnabled && mWifiVisible; apply(); } @Override - public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, + public void setMobileDataIndicators(IconState icon, IconState qsIcon, int type, int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, String description, boolean isWide, int subId, boolean roaming) { PhoneState state = getState(subId); if (state == null) { return; } - state.mMobileVisible = statusIcon.visible && !mBlockMobile; - state.mMobileStrengthId = statusIcon.icon; - state.mMobileTypeId = statusType; - state.mMobileDescription = statusIcon.contentDescription; + if (mQsSignal) { + icon = qsIcon; + type = qsType; + } + state.mMobileVisible = icon.visible && !mBlockMobile; + state.mMobileStrengthId = icon.icon; + state.mMobileTypeId = type; + state.mMobileDescription = icon.contentDescription; state.mMobileTypeDescription = typeContentDescription; - state.mIsMobileTypeIconWide = statusType != 0 && isWide; + state.mIsMobileTypeIconWide = type != 0 && isWide; state.mRoaming = roaming; state.mActivityIn = activityIn && mActivityEnabled; state.mActivityOut = activityOut && mActivityEnabled; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index c7fbbf956c68..85475b60902f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -179,6 +179,10 @@ public class StatusBarIconView extends AnimatedImageView { mIconScale = (float)imageBounds / (float)outerBounds; } + public float getIconScaleFullyDark() { + return (float) mStatusBarIconDrawingSizeDark / mStatusBarIconDrawingSize; + } + public float getIconScale() { return mIconScale; } 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 4bfc16b7b4d6..d047fa929da2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -545,7 +545,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { } private boolean onLongPressRecents() { - if (mRecents == null || !ActivityManager.supportsMultiWindow() + if (mRecents == null || !ActivityManager.supportsMultiWindow(getContext()) || !mDivider.getView().getSnapAlgorithm().isSplitScreenFeasible()) { return false; } 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 9000eb4655d1..f94bb0cdd4f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java @@ -267,6 +267,9 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { boolean forceOverflow = mSpeedBumpIndex != -1 && i >= mSpeedBumpIndex && iconState.iconAppearAmount > 0.0f || i >= maxVisibleIcons; boolean noOverflowAfter = i == childCount - 1; + float drawingScale = mDark && view instanceof StatusBarIconView + ? ((StatusBarIconView) view).getIconScaleFullyDark() + : 1f; if (mOpenedAmount != 0.0f) { noOverflowAfter = noOverflowAfter && !hasAmbient && !forceOverflow; } @@ -303,7 +306,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { visualOverflowStart += mVisualOverflowAdaption * (1f - mOpenedAmount); } } - translationX += iconState.iconAppearAmount * view.getWidth(); + translationX += iconState.iconAppearAmount * view.getWidth() * drawingScale; } if (firstOverflowIndex != -1) { int numDots = 1; 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 51fb204f13a0..24c19282a4f6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -759,6 +759,7 @@ public class StatusBar extends SystemUI implements DemoMode, mBatteryController = Dependency.get(BatteryController.class); mAssistManager = Dependency.get(AssistManager.class); mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); + mSystemServicesProxy = SystemServicesProxy.getInstance(mContext); mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); mDisplay = mWindowManager.getDefaultDisplay(); @@ -1825,23 +1826,20 @@ public class StatusBar extends SystemUI implements DemoMode, // temporarily become children if they were isolated before. continue; } - int vis = ent.notification.getNotification().visibility; int userId = ent.notification.getUserId(); // Display public version of the notification if we need to redact. - boolean deviceSensitive = (isLockscreenPublicMode(mCurrentUserId) - && !userAllowsPrivateNotificationsInPublic(mCurrentUserId)); - boolean userSensitive = deviceSensitive || (isLockscreenPublicMode(userId) - && !userAllowsPrivateNotificationsInPublic(userId)); - boolean sensitiveNote = vis == Notification.VISIBILITY_PRIVATE; - boolean sensitivePackage = packageHasVisibilityOverride(ent.notification.getKey()); - boolean sensitive = (sensitiveNote && userSensitive) || sensitivePackage; - boolean showingPublic = sensitive && isLockscreenPublicMode(userId); - if (showingPublic) { + boolean devicePublic = isLockscreenPublicMode(mCurrentUserId); + boolean userPublic = devicePublic || isLockscreenPublicMode(userId); + boolean needsRedaction = needsRedaction(ent); + boolean sensitive = userPublic && needsRedaction; + boolean deviceSensitive = devicePublic + && !userAllowsPrivateNotificationsInPublic(mCurrentUserId); + if (sensitive) { updatePublicContentView(ent, ent.notification); } ent.row.setSensitive(sensitive, deviceSensitive); - ent.row.setNeedsRedaction(needsRedaction(ent)); + ent.row.setNeedsRedaction(needsRedaction); if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) { ExpandableNotificationRow summary = mGroupManager.getGroupSummary( ent.row.getStatusBarNotification()); @@ -4320,7 +4318,12 @@ public class StatusBar extends SystemUI implements DemoMode, final int userId = mCurrentProfiles.valueAt(i).id; boolean isProfilePublic = devicePublic; if (!devicePublic && userId != mCurrentUserId) { - if (mStatusBarKeyguardViewManager.isSecure(userId)) { + // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge + // due to a race condition where this code could be called before + // TrustManagerService updates its internal records, resulting in an incorrect + // state being cached in mLockscreenPublicMode. (b/35951989) + if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) + && mStatusBarKeyguardViewManager.isSecure(userId)) { isProfilePublic = mKeyguardManager.isDeviceLocked(userId); } } @@ -5192,6 +5195,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected KeyguardManager mKeyguardManager; private LockPatternUtils mLockPatternUtils; private DeviceProvisionedController mDeviceProvisionedController; + protected SystemServicesProxy mSystemServicesProxy; // UI-specific methods @@ -6816,6 +6820,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) { if (!mUseHeadsUp || isDeviceInVrMode()) { + if (DEBUG) Log.d(TAG, "No peeking: no huns or vr mode"); return false; } @@ -6824,8 +6829,7 @@ public class StatusBar extends SystemUI implements DemoMode, return false; } - boolean inUse = mPowerManager.isScreenOn() - && !SystemServicesProxy.getInstance(mContext).isDreaming(); + boolean inUse = mPowerManager.isScreenOn() && !mSystemServicesProxy.isDreaming(); if (!inUse && !isDozing()) { if (DEBUG) { @@ -6868,6 +6872,12 @@ public class StatusBar extends SystemUI implements DemoMode, } } + // Don't peek notifications that are suppressed due to group alert behavior + if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) { + if (DEBUG) Log.d(TAG, "No peeking: suppressed due to group alert behavior"); + return false; + } + return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 67b5596e34c9..03a50a209de1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -253,11 +253,6 @@ public class MobileSignalController extends SignalController< } @Override - public int getQsCurrentIconId() { - return getCurrentIconId(); - } - - @Override public void notifyListeners(SignalCallback callback) { MobileIconGroup icons = getIcons(); @@ -276,9 +271,9 @@ public class MobileSignalController extends SignalController< String description = null; // Only send data sim callbacks to QS. if (mCurrentState.dataSim) { - qsTypeIcon = showDataIcon ? icons.mQsDataType : 0; + qsTypeIcon = showDataIcon ? icons.mDataType : 0; qsIcon = new IconState(mCurrentState.enabled - && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription); + && !mCurrentState.isEmergency, getCurrentIconId(), contentDescription); description = mCurrentState.isEmergency ? null : mCurrentState.networkName; } boolean activityIn = mCurrentState.dataConnected diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index aaa0568a72cd..d91ae39bc920 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -22,16 +22,6 @@ import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGr class TelephonyIcons { //***** Data connection icons - static final int QS_DATA_G = R.drawable.ic_qs_signal_g; - static final int QS_DATA_3G = R.drawable.ic_qs_signal_3g; - static final int QS_DATA_E = R.drawable.ic_qs_signal_e; - static final int QS_DATA_H = R.drawable.ic_qs_signal_h; - static final int QS_DATA_1X = R.drawable.ic_qs_signal_1x; - static final int QS_DATA_4G = R.drawable.ic_qs_signal_4g; - static final int QS_DATA_4G_PLUS = R.drawable.ic_qs_signal_4g_plus; - static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte; - static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus; - static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode; static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte; @@ -46,8 +36,6 @@ class TelephonyIcons { static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled; - static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled; - static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup( "CARRIER_NETWORK_CHANGE", null, @@ -75,7 +63,7 @@ class TelephonyIcons { R.string.accessibility_data_connection_3g, TelephonyIcons.ICON_3G, true, - TelephonyIcons.QS_DATA_3G + TelephonyIcons.ICON_3G ); static final MobileIconGroup WFC = new MobileIconGroup( @@ -114,7 +102,7 @@ class TelephonyIcons { R.string.accessibility_data_connection_edge, TelephonyIcons.ICON_E, false, - TelephonyIcons.QS_DATA_E + TelephonyIcons.ICON_E ); static final MobileIconGroup ONE_X = new MobileIconGroup( @@ -129,7 +117,7 @@ class TelephonyIcons { R.string.accessibility_data_connection_cdma, TelephonyIcons.ICON_1X, true, - TelephonyIcons.QS_DATA_1X + TelephonyIcons.ICON_1X ); static final MobileIconGroup G = new MobileIconGroup( @@ -144,7 +132,7 @@ class TelephonyIcons { R.string.accessibility_data_connection_gprs, TelephonyIcons.ICON_G, false, - TelephonyIcons.QS_DATA_G + TelephonyIcons.ICON_G ); static final MobileIconGroup H = new MobileIconGroup( @@ -159,7 +147,7 @@ class TelephonyIcons { R.string.accessibility_data_connection_3_5g, TelephonyIcons.ICON_H, false, - TelephonyIcons.QS_DATA_H + TelephonyIcons.ICON_H ); static final MobileIconGroup FOUR_G = new MobileIconGroup( @@ -174,7 +162,7 @@ class TelephonyIcons { R.string.accessibility_data_connection_4g, TelephonyIcons.ICON_4G, true, - TelephonyIcons.QS_DATA_4G + TelephonyIcons.ICON_4G ); static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup( @@ -189,7 +177,7 @@ class TelephonyIcons { R.string.accessibility_data_connection_4g_plus, TelephonyIcons.ICON_4G_PLUS, true, - TelephonyIcons.QS_DATA_4G_PLUS + TelephonyIcons.ICON_4G_PLUS ); static final MobileIconGroup LTE = new MobileIconGroup( @@ -204,7 +192,7 @@ class TelephonyIcons { R.string.accessibility_data_connection_lte, TelephonyIcons.ICON_LTE, true, - TelephonyIcons.QS_DATA_LTE + TelephonyIcons.ICON_LTE ); static final MobileIconGroup LTE_PLUS = new MobileIconGroup( @@ -219,7 +207,7 @@ class TelephonyIcons { R.string.accessibility_data_connection_lte_plus, TelephonyIcons.ICON_LTE_PLUS, true, - TelephonyIcons.QS_DATA_LTE_PLUS + TelephonyIcons.ICON_LTE_PLUS ); static final MobileIconGroup DATA_DISABLED = new MobileIconGroup( @@ -234,7 +222,7 @@ class TelephonyIcons { R.string.accessibility_cell_data_off, TelephonyIcons.ICON_DATA_DISABLED, false, - TelephonyIcons.QS_ICON_DATA_DISABLED + TelephonyIcons.ICON_DATA_DISABLED ); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java index e80d3b3a6409..0fd244527540 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java @@ -36,11 +36,13 @@ import android.service.notification.Condition; import android.service.notification.IConditionListener; import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig.ZenRule; +import android.support.annotation.VisibleForTesting; import android.util.Log; import android.util.Slog; import com.android.systemui.qs.GlobalSetting; import com.android.systemui.settings.CurrentUserTracker; +import com.android.systemui.util.Utils; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -169,45 +171,32 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode } private void fireNextAlarmChanged() { - for (Callback cb : mCallbacks) { - cb.onNextAlarmChanged(); - } + Utils.safeForeach(mCallbacks, c -> c.onNextAlarmChanged()); } private void fireEffectsSuppressorChanged() { - for (Callback cb : mCallbacks) { - cb.onEffectsSupressorChanged(); - } + Utils.safeForeach(mCallbacks, c -> c.onEffectsSupressorChanged()); } private void fireZenChanged(int zen) { - for (Callback cb : mCallbacks) { - cb.onZenChanged(zen); - } + Utils.safeForeach(mCallbacks, c -> c.onZenChanged(zen)); } private void fireZenAvailableChanged(boolean available) { - for (Callback cb : mCallbacks) { - cb.onZenAvailableChanged(available); - } + Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available)); } private void fireConditionsChanged(Condition[] conditions) { - for (Callback cb : mCallbacks) { - cb.onConditionsChanged(conditions); - } + Utils.safeForeach(mCallbacks, c -> c.onConditionsChanged(conditions)); } private void fireManualRuleChanged(ZenRule rule) { - for (Callback cb : mCallbacks) { - cb.onManualRuleChanged(rule); - } + Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule)); } - private void fireConfigChanged(ZenModeConfig config) { - for (Callback cb : mCallbacks) { - cb.onConfigChanged(config); - } + @VisibleForTesting + protected void fireConfigChanged(ZenModeConfig config) { + Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config)); } private void updateConditions(Condition[] conditions) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java index 0dbd1d6cc74a..ff06b5b33a05 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java @@ -300,7 +300,7 @@ public class NotificationChildrenContainer extends ViewGroup { mNotificationHeaderWrapper.notifyContentUpdated(mContainingNotification); recreateLowPriorityHeader(builder); recreateAmbientHeader(builder); - resetHeaderVisibilityIfNeeded(mNotificationHeader, calculateDesiredHeader()); + updateHeaderVisibility(false /* animate */); updateChildrenHeaderAppearance(); } @@ -833,6 +833,11 @@ public class NotificationChildrenContainer extends ViewGroup { return mNotificationHeaderLowPriority; } + @VisibleForTesting + public ViewGroup getCurrentHeaderView() { + return mCurrentHeader; + } + public void notifyShowAmbientChanged() { updateHeaderVisibility(false); } @@ -869,7 +874,12 @@ public class NotificationChildrenContainer extends ViewGroup { desiredHeader.setVisibility(VISIBLE); } if (currentHeader != null) { - getWrapperForView(currentHeader).setVisible(false); + // Wrapper can be null if we were a low priority notification + // and just destroyed it by calling setIsLowPriority(false) + NotificationViewWrapper wrapper = getWrapperForView(currentHeader); + if (wrapper != null) { + wrapper.setVisible(false); + } currentHeader.setVisibility(INVISIBLE); } } @@ -878,7 +888,7 @@ public class NotificationChildrenContainer extends ViewGroup { resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, desiredHeader); resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, desiredHeader); - mCurrentHeader = currentHeader; + mCurrentHeader = desiredHeader; } private void resetHeaderVisibilityIfNeeded(View header, View desiredHeader) { diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java new file mode 100644 index 000000000000..f4aebae7bdaf --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java @@ -0,0 +1,31 @@ +/* + * 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 com.android.systemui.util; + +import java.util.List; +import java.util.function.Consumer; + +public class Utils { + + /** + * Allows lambda iteration over a list. It is done in reverse order so it is safe + * to add or remove items during the iteration. + */ + public static <T> void safeForeach(List<T> list, Consumer<T> c) { + for (int i = list.size() - 1; i >= 0; i--) { + c.accept(list.get(i)); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java index 51fcdbb92c81..ecdea4f442b2 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java @@ -57,7 +57,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Prefs; import com.android.systemui.R; -import com.android.systemui.R.string; import com.android.systemui.statusbar.policy.ZenModeController; import java.io.FileDescriptor; @@ -294,11 +293,6 @@ public class ZenModePanel extends FrameLayout { private void onAttach() { setExpanded(true); mAttached = true; - for (int i = 0; i < mZenRadioGroupContent.getChildCount(); i++) { - ConditionTag tag = getConditionTagAt(i); - if (tag != null) tag.rb.setChecked(false); - mZenRadioGroupContent.getChildAt(i).setTag(null); - } mAttachedZen = mController.getZen(); ZenRule manualRule = mController.getManualRule(); mExitCondition = manualRule != null ? manualRule.condition : null; @@ -311,6 +305,7 @@ public class ZenModePanel extends FrameLayout { setSessionExitCondition(copy(mExitCondition)); updateWidgets(); setRequestingConditions(!mHidden); + ensureSelection(); } private void onDetach() { @@ -366,9 +361,6 @@ public class ZenModePanel extends FrameLayout { if (expanded == mExpanded) return; if (DEBUG) Log.d(mTag, "setExpanded " + expanded); mExpanded = expanded; - if (mExpanded) { - ensureSelection(); - } updateWidgets(); fireExpanded(); } @@ -464,7 +456,8 @@ public class ZenModePanel extends FrameLayout { ActivityManager.getCurrentUser(), false); return c; } - return null; + // If there is a manual rule, but it has no condition listed then it is forever. + return forever(); } private void handleUpdateZen(int zen) { @@ -491,6 +484,7 @@ public class ZenModePanel extends FrameLayout { final ConditionTag tag = getConditionTagAt(i); if (tag != null && sameConditionId(tag.condition, mExitCondition)) { bind(exitCondition, mZenRadioGroupContent.getChildAt(i), i); + tag.rb.setChecked(true); return; } } @@ -498,6 +492,7 @@ public class ZenModePanel extends FrameLayout { exitCondition.id)) { bind(exitCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX), COUNTDOWN_CONDITION_INDEX); + getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index bf6b3946d101..55ec3079bdbb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -16,13 +16,27 @@ package com.android.systemui.statusbar.phone; +import static android.app.NotificationManager.IMPORTANCE_HIGH; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.app.Notification; import android.metrics.LogMaker; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IPowerManager; +import android.os.Looper; +import android.os.PowerManager; +import android.os.UserHandle; +import android.service.notification.StatusBarNotification; import android.support.test.filters.SmallTest; import android.support.test.metricshelper.MetricsAsserts; import android.support.test.runner.AndroidJUnit4; @@ -33,9 +47,11 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.keyguard.KeyguardHostView.OnDismissAction; import com.android.systemui.SysuiTestCase; +import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.statusbar.ActivatableNotificationView; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.NotificationData; +import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import org.junit.Before; @@ -52,19 +68,34 @@ public class StatusBarTest extends SysuiTestCase { NotificationStackScrollLayout mStackScroller; StatusBar mStatusBar; FakeMetricsLogger mMetricsLogger; + HeadsUpManager mHeadsUpManager; + NotificationData mNotificationData; + PowerManager mPowerManager; + SystemServicesProxy mSystemServicesProxy; private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); @Before - public void setup() { + public void setup() throws Exception { mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager.class); mUnlockMethodCache = mock(UnlockMethodCache.class); mKeyguardIndicationController = mock(KeyguardIndicationController.class); mStackScroller = mock(NotificationStackScrollLayout.class); mMetricsLogger = new FakeMetricsLogger(); + mHeadsUpManager = mock(HeadsUpManager.class); + mNotificationData = mock(NotificationData.class); + mSystemServicesProxy = mock(SystemServicesProxy.class); + IPowerManager powerManagerService = mock(IPowerManager.class); + HandlerThread handlerThread = new HandlerThread("TestThread"); + handlerThread.start(); + mPowerManager = new PowerManager(mContext, powerManagerService, + new Handler(handlerThread.getLooper())); + when(powerManagerService.isInteractive()).thenReturn(true); + mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache, - mKeyguardIndicationController, mStackScroller); + mKeyguardIndicationController, mStackScroller, mHeadsUpManager, + mNotificationData, mPowerManager, mSystemServicesProxy); doAnswer(invocation -> { OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0]; @@ -210,14 +241,62 @@ public class StatusBarTest extends SysuiTestCase { .setType(MetricsEvent.TYPE_ACTION)); } + @Test + public void testShouldPeek_nonSuppressedGroupSummary() { + when(mPowerManager.isScreenOn()).thenReturn(true); + when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false); + when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false); + when(mNotificationData.shouldFilterOut(any())).thenReturn(false); + when(mSystemServicesProxy.isDreaming()).thenReturn(false); + when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH); + + Notification n = new Notification.Builder(getContext(), "a") + .setGroup("a") + .setGroupSummary(true) + .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY) + .build(); + StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, + UserHandle.of(0), null, 0); + NotificationData.Entry entry = new NotificationData.Entry(sbn); + + assertTrue(mStatusBar.shouldPeek(entry, sbn)); + } + + @Test + public void testShouldPeek_suppressedGroupSummary() { + when(mPowerManager.isScreenOn()).thenReturn(true); + when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false); + when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false); + when(mNotificationData.shouldFilterOut(any())).thenReturn(false); + when(mSystemServicesProxy.isDreaming()).thenReturn(false); + when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH); + + Notification n = new Notification.Builder(getContext(), "a") + .setGroup("a") + .setGroupSummary(true) + .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN) + .build(); + StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, + UserHandle.of(0), null, 0); + NotificationData.Entry entry = new NotificationData.Entry(sbn); + + assertFalse(mStatusBar.shouldPeek(entry, sbn)); + } + static class TestableStatusBar extends StatusBar { public TestableStatusBar(StatusBarKeyguardViewManager man, UnlockMethodCache unlock, KeyguardIndicationController key, - NotificationStackScrollLayout stack) { + NotificationStackScrollLayout stack, HeadsUpManager hum, NotificationData nd, + PowerManager pm, SystemServicesProxy ssp) { mStatusBarKeyguardViewManager = man; mUnlockMethodCache = unlock; mKeyguardIndicationController = key; mStackScroller = stack; + mHeadsUpManager = hum; + mNotificationData = nd; + mUseHeadsUp = true; + mPowerManager = pm; + mSystemServicesProxy = ssp; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java index cb2063967639..6157d44d1319 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java @@ -111,7 +111,7 @@ public class CallbackHandlerTest extends SysuiTestCase { String typeDescription = "Test 1"; String description = "Test 2"; int type = R.drawable.stat_sys_data_fully_connected_1x; - int qsType = R.drawable.ic_qs_signal_1x; + int qsType = type; boolean wide = true; int subId = 5; boolean roaming = true; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 505e1d8346fd..c233fea3c495 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -70,7 +70,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected static final int DEFAULT_SIGNAL_STRENGTH = DEFAULT_LEVEL; protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL; protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G; - protected static final int DEFAULT_QS_ICON = TelephonyIcons.QS_DATA_3G; + protected static final int DEFAULT_QS_ICON = DEFAULT_ICON; protected NetworkControllerImpl mNetworkController; protected MobileSignalController mMobileSignalController; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index dfe00f95fe4d..ac64263c3eb9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -25,7 +25,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { setupDefaultSignal(); verifyDataIndicators(TelephonyIcons.ICON_3G, - TelephonyIcons.QS_DATA_3G); + TelephonyIcons.ICON_3G); } @Test @@ -35,7 +35,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyManager.NETWORK_TYPE_GSM); verifyDataIndicators(TelephonyIcons.ICON_G, - TelephonyIcons.QS_DATA_G); + TelephonyIcons.ICON_G); } @Test @@ -45,7 +45,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyManager.NETWORK_TYPE_CDMA); verifyDataIndicators(TelephonyIcons.ICON_1X, - TelephonyIcons.QS_DATA_1X); + TelephonyIcons.ICON_1X); } @Test @@ -55,7 +55,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyManager.NETWORK_TYPE_EDGE); verifyDataIndicators(TelephonyIcons.ICON_E, - TelephonyIcons.QS_DATA_E); + TelephonyIcons.ICON_E); } @Test @@ -65,7 +65,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyManager.NETWORK_TYPE_LTE); verifyDataIndicators(TelephonyIcons.ICON_LTE, - TelephonyIcons.QS_DATA_LTE); + TelephonyIcons.ICON_LTE); } @Test @@ -75,7 +75,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyManager.NETWORK_TYPE_HSPA); verifyDataIndicators(TelephonyIcons.ICON_H, - TelephonyIcons.QS_DATA_H); + TelephonyIcons.ICON_H); } @Test @@ -104,7 +104,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyManager.NETWORK_TYPE_LTE); verifyDataIndicators(TelephonyIcons.ICON_4G, - TelephonyIcons.QS_DATA_4G); + TelephonyIcons.ICON_4G); } @Ignore("Flaky") @@ -117,7 +117,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); verifyDataIndicators(TelephonyIcons.ICON_DATA_DISABLED, - TelephonyIcons.QS_ICON_DATA_DISABLED); + TelephonyIcons.ICON_DATA_DISABLED); } @Test @@ -148,7 +148,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mNetworkController.handleConfigurationChanged(); verifyDataIndicators(TelephonyIcons.ICON_4G, - TelephonyIcons.QS_DATA_4G); + TelephonyIcons.ICON_4G); } @Test @@ -158,13 +158,13 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyManager.NETWORK_TYPE_LTE); verifyDataIndicators(TelephonyIcons.ICON_LTE, - TelephonyIcons.QS_DATA_LTE); + TelephonyIcons.ICON_LTE); when(mServiceState.getDataNetworkType()) .thenReturn(TelephonyManager.NETWORK_TYPE_HSPA); updateServiceState(); verifyDataIndicators(TelephonyIcons.ICON_H, - TelephonyIcons.QS_DATA_H); + TelephonyIcons.ICON_H); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index 1627925ae1bc..aa62075530eb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -214,7 +214,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { verifyLastQsMobileDataIndicators(true, testStrength, - TelephonyIcons.QS_DATA_1X, false, false); + TelephonyIcons.ICON_1X, false, false); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java new file mode 100644 index 000000000000..8124bf39328b --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java @@ -0,0 +1,56 @@ +/* + * 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 com.android.systemui.statusbar.policy; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.os.Handler; +import android.service.notification.ZenModeConfig; +import android.support.test.filters.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.policy.ZenModeController.Callback; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@RunWithLooper +public class ZenModeControllerImplTest extends SysuiTestCase { + + private Callback mCallback; + + @Test + public void testRemoveDuringCallback() { + ZenModeControllerImpl controller = new ZenModeControllerImpl(mContext, new Handler()); + mCallback = new Callback() { + @Override + public void onConfigChanged(ZenModeConfig config) { + controller.removeCallback(mCallback); + } + }; + controller.addCallback(mCallback); + Callback mockCallback = mock(Callback.class); + controller.addCallback(mockCallback); + controller.fireConfigChanged(null); + verify(mockCallback).onConfigChanged(eq(null)); + } + +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java index e6c8815b9e21..2dd96b686996 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java @@ -60,4 +60,12 @@ public class NotificationChildrenContainerTest extends SysuiTestCase { Assert.assertTrue(lowPriorityHeaderView.getParent() == null); Assert.assertTrue(childrenContainer.getLowPriorityHeaderView() == null); } + + @Test + public void testRecreateNotificationHeader_hasHeader() { + NotificationChildrenContainer childrenContainer = mGroup.getChildrenContainer(); + childrenContainer.recreateNotificationHeader(null); + Assert.assertNotNull("Children container must have a header after recreation", + childrenContainer.getCurrentHeaderView()); + } } diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 7abaf7ff9922..38b796b316de 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -51,6 +51,7 @@ import android.service.autofill.FillEventHistory.Event; import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.text.TextUtils; +import android.util.ArraySet; import android.util.LocalLog; import android.util.Slog; import android.util.SparseArray; @@ -465,10 +466,17 @@ final class AutofillManagerServiceImpl { if (sVerbose) Slog.v(TAG, "destroyLocked()"); final int numSessions = mSessions.size(); + final ArraySet<RemoteFillService> remoteFillServices = new ArraySet<>(numSessions); for (int i = 0; i < numSessions; i++) { - mSessions.valueAt(i).destroyLocked(); + final RemoteFillService remoteFillService = mSessions.valueAt(i).destroyLocked(); + if (remoteFillService != null) { + remoteFillServices.add(remoteFillService); + } } mSessions.clear(); + for (int i = 0; i < remoteFillServices.size(); i++) { + remoteFillServices.valueAt(i).destroy(); + } sendStateToClients(true); } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index bad8dcf42aae..980a7d41200f 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -419,7 +419,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState notifyUnavailableToClient(); } synchronized (mLock) { - processResponseLocked(response); + processResponseLocked(response, requestFlags); } final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST)) @@ -1026,7 +1026,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState case ACTION_START_SESSION: // View is triggering autofill. mCurrentViewId = viewState.id; - viewState.update(value, virtualBounds); + viewState.update(value, virtualBounds, flags); viewState.setState(ViewState.STATE_STARTED_SESSION); requestNewFillResponseLocked(flags); break; @@ -1065,7 +1065,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } // If the ViewState is ready to be displayed, onReady() will be called. - viewState.update(value, virtualBounds); + viewState.update(value, virtualBounds, flags); break; case ACTION_VIEW_EXITED: if (mCurrentViewId == viewState.id) { @@ -1204,10 +1204,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // Replace the old response mResponses.put(newResponse.getRequestId(), newResponse); // Now process the new response - processResponseLocked(newResponse); + processResponseLocked(newResponse, 0); } - private void processResponseLocked(@NonNull FillResponse newResponse) { + private void processResponseLocked(@NonNull FillResponse newResponse, int flags) { // Make sure we are hiding the UI which will be shown // only if handling the current response requires it. hideAllUiIfOwnedByMe(); @@ -1215,7 +1215,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final int requestId = newResponse.getRequestId(); if (sVerbose) { Slog.v(TAG, "processResponseLocked(): mCurrentViewId=" + mCurrentViewId - + ", reqId=" + requestId + ", resp=" + newResponse); + + ",flags=" + flags + ", reqId=" + requestId + ", resp=" + newResponse); } if (mResponses == null) { @@ -1231,21 +1231,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } - final ArrayList<Dataset> datasets = newResponse.getDatasets(); - - if (datasets != null && datasets.size() == 1) { - // Check if it its a single response for a manual request, in which case it should - // be automatically filled - final FillContext context = getFillContextByRequestIdLocked(requestId); - if (context != null && (context.getStructure().getFlags() & FLAG_MANUAL_REQUEST) != 0) { - Slog.d(TAG, "autofilling manual request directly"); - autoFill(requestId, 0, datasets.get(0)); - return; - } - } // Updates the UI, if necessary. final ViewState currentView = mViewStates.get(mCurrentViewId); - currentView.maybeCallOnFillReady(); + currentView.maybeCallOnFillReady(flags); } /** @@ -1331,20 +1319,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return viewState; } - /** - * Resets the given state from all existing views in the given dataset. - */ - private void resetViewStatesLocked(@NonNull Dataset dataset, int state) { - final ArrayList<AutofillId> ids = dataset.getFieldIds(); - for (int j = 0; j < ids.size(); j++) { - final AutofillId id = ids.get(j); - final ViewState viewState = mViewStates.get(id); - if (viewState != null) { - viewState.resetState(state); - } - } - } - void autoFill(int requestId, int datasetIndex, Dataset dataset) { synchronized (mLock) { if (mDestroyed) { @@ -1452,8 +1426,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } try { - if (sDebug) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); - // Skip null values as a null values means no change final int entryCount = dataset.getFieldIds().size(); final List<AutofillId> ids = new ArrayList<>(entryCount); @@ -1480,6 +1452,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (waitingDatasetAuth) { hideFillUiIfOwnedByMe(); } + if (sDebug) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); + mClient.autofill(id, ids, values); setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED, false); } @@ -1496,15 +1470,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - void destroyLocked() { + RemoteFillService destroyLocked() { if (mDestroyed) { - return; + return null; } - mRemoteFillService.destroy(); hideAllUiIfOwnedByMe(); mUi.clearCallback(this); mDestroyed = true; mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_FINISHED, mPackageName); + return mRemoteFillService; } private void hideAllUiIfOwnedByMe() { @@ -1528,8 +1502,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState + id + " destroyed"); return; } - destroyLocked(); + final RemoteFillService remoteFillService = destroyLocked(); mService.removeSessionLocked(id); + if (remoteFillService != null) { + remoteFillService.destroy(); + } } private int getLastResponseIndex() { diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java index 8a52c965345c..cd8f4a59526f 100644 --- a/services/autofill/java/com/android/server/autofill/ViewState.java +++ b/services/autofill/java/com/android/server/autofill/ViewState.java @@ -16,6 +16,7 @@ package com.android.server.autofill; +import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sVerbose; @@ -157,7 +158,7 @@ final class ViewState { // TODO: refactor / rename / document this method (and maybeCallOnFillReady) to make it clear // that it can change the value and update the UI; similarly, should replace code that // directly sets mAutofillValue to use encapsulation. - void update(@Nullable AutofillValue autofillValue, @Nullable Rect virtualBounds) { + void update(@Nullable AutofillValue autofillValue, @Nullable Rect virtualBounds, int flags) { if (autofillValue != null) { mCurrentValue = autofillValue; } @@ -165,7 +166,7 @@ final class ViewState { mVirtualBounds = virtualBounds; } - maybeCallOnFillReady(); + maybeCallOnFillReady(flags); } /** @@ -173,8 +174,8 @@ final class ViewState { * Listener#onFillReady(FillResponse, AutofillId, AutofillValue)} if the * fill UI is ready to be displayed (i.e. when response and bounds are set). */ - void maybeCallOnFillReady() { - if ((mState & STATE_AUTOFILLED) != 0) { + void maybeCallOnFillReady(int flags) { + if ((mState & STATE_AUTOFILLED) != 0 && (flags & FLAG_MANUAL_REQUEST) == 0) { if (sDebug) Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString()); return; } diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java index d315b3d7b70f..d566d3d608b4 100644 --- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java @@ -158,6 +158,7 @@ final class FillUi { final RemoteViews presentation = dataset.getFieldPresentation(index); final View view; try { + if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId); view = presentation.apply(context, null, interceptionHandler); } catch (RuntimeException e) { Slog.e(TAG, "Error inflating remote views", e); @@ -203,6 +204,7 @@ final class FillUi { return; } if (count <= 0) { + if (sDebug) Slog.d(TAG, "No dataset matches filter: " + mFilterText); mCallback.requestHideFillUi(); } else { if (updateContentSize()) { @@ -382,6 +384,7 @@ final class FillUi { * Shows the window. */ public void show(WindowManager.LayoutParams params) { + if (sVerbose) Slog.v(TAG, "show(): showing=" + mShowing + ", params="+ params); try { if (!mShowing) { params.accessibilityTitle = mContentView.getContext() diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index 6502c012ef5b..68f8c1bb182f 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -41,14 +41,10 @@ option java_package com.android.server # --------------------------- # DeviceStorageMonitorService.java # --------------------------- -# The disk space free on the /data partition, in bytes -2744 free_storage_changed (data|2|2) -# Device low memory notification and disk space free on the /data partition, in bytes at that time -2745 low_storage (data|2|2) -# disk space free on the /data, /system, and /cache partitions in bytes -2746 free_storage_left (data|2|2),(system|2|2),(cache|2|2) -# file on cache partition was deleted +# File on cache partition was deleted 2748 cache_file_deleted (path|3) +# Storage volume state and usable space in bytes +2749 storage_state (uuid|3),(old_state|1),(new_state|1),(usable|2),(total|2) # --------------------------- diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index cffb158a3f21..35b452a12e64 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -3296,6 +3296,9 @@ class StorageManagerService extends IStorageManager.Stub final StorageManager storage = mContext.getSystemService(StorageManager.class); final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class); + // Apps can't defy reserved space + flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_RESERVED; + final boolean aggressive = (flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0; if (aggressive) { mContext.enforceCallingOrSelfPermission( @@ -3306,24 +3309,31 @@ class StorageManagerService extends IStorageManager.Stub try { // In general, apps can allocate as much space as they want, except // we never let them eat into either the minimum cache space or into - // the low disk warning space. + // the low disk warning space. To avoid user confusion, this logic + // should be kept in sync with getFreeBytes(). final File path = storage.findPathForUuid(volumeUuid); + + final long usable = path.getUsableSpace(); + final long lowReserved = storage.getStorageLowBytes(path); + final long fullReserved = storage.getStorageFullBytes(path); + if (stats.isQuotaSupported(volumeUuid)) { + final long cacheTotal = stats.getCacheBytes(volumeUuid); + final long cacheReserved = storage.getStorageCacheBytes(path); + final long cacheClearable = Math.max(0, cacheTotal - cacheReserved); + if (aggressive) { - return Math.max(0, - stats.getFreeBytes(volumeUuid) - storage.getStorageFullBytes(path)); + return Math.max(0, (usable + cacheTotal) - fullReserved); } else { - return Math.max(0, - stats.getFreeBytes(volumeUuid) - storage.getStorageLowBytes(path) - - storage.getStorageCacheBytes(path)); + return Math.max(0, (usable + cacheClearable) - lowReserved); } } else { // When we don't have fast quota information, we ignore cached // data and only consider unused bytes. if (aggressive) { - return Math.max(0, path.getUsableSpace() - storage.getStorageFullBytes(path)); + return Math.max(0, usable - fullReserved); } else { - return Math.max(0, path.getUsableSpace() - storage.getStorageLowBytes(path)); + return Math.max(0, usable - lowReserved); } } } catch (IOException e) { @@ -3337,6 +3347,9 @@ class StorageManagerService extends IStorageManager.Stub public void allocateBytes(String volumeUuid, long bytes, int flags) { final StorageManager storage = mContext.getSystemService(StorageManager.class); + // Apps can't defy reserved space + flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_RESERVED; + // This method call will enforce FLAG_ALLOCATE_AGGRESSIVE permissions so // we don't have to enforce them locally final long allocatableBytes = getAllocatableBytes(volumeUuid, flags); @@ -3350,7 +3363,11 @@ class StorageManagerService extends IStorageManager.Stub // Free up enough disk space to satisfy both the requested allocation // and our low disk warning space. final File path = storage.findPathForUuid(volumeUuid); - bytes += storage.getStorageLowBytes(path); + if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { + bytes += storage.getStorageFullBytes(path); + } else { + bytes += storage.getStorageLowBytes(path); + } mPms.freeStorage(volumeUuid, bytes, flags); } catch (IOException e) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index fbab26aa0339..c92c36052e72 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8447,8 +8447,8 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (mPidsSelfLocked) { proc = mPidsSelfLocked.get(callingPid); } - if (proc != null && proc.curProcState - < ActivityManager.PROCESS_STATE_RECEIVER) { + if (proc != null && + !ActivityManager.isProcStateBackground(proc.curProcState)) { // Whoever is instigating this is in the foreground, so we will allow it // to go through. return ActivityManager.APP_START_MODE_NORMAL; @@ -13545,7 +13545,9 @@ public class ActivityManagerService extends IActivityManager.Stub return; } if (pr.hasTopUi != hasTopUi) { - Slog.i(TAG, "Setting hasTopUi=" + hasTopUi + " for pid=" + pid); + if (DEBUG_OOM_ADJ) { + Slog.d(TAG, "Setting hasTopUi=" + hasTopUi + " for pid=" + pid); + } pr.hasTopUi = hasTopUi; changed = true; } @@ -13922,9 +13924,9 @@ public class ActivityManagerService extends IActivityManager.Stub final boolean supportsPictureInPicture = mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE); - final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow(); + final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow(mContext); final boolean supportsSplitScreenMultiWindow = - ActivityManager.supportsSplitScreenMultiWindow(); + ActivityManager.supportsSplitScreenMultiWindow(mContext); final boolean supportsMultiDisplay = mContext.getPackageManager() .hasSystemFeature(FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS); final String debugApp = Settings.Global.getString(resolver, DEBUG_APP); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 6eae9e6f9b05..d7683047143a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -2382,7 +2382,7 @@ final class ActivityManagerShellCommand extends ShellCommand { if (res == null) { return -1; } - pw.println(ActivityManager.supportsMultiWindow()); + pw.println(ActivityManager.supportsMultiWindow(mInternal.mContext)); return 0; } @@ -2391,7 +2391,7 @@ final class ActivityManagerShellCommand extends ShellCommand { if (res == null) { return -1; } - pw.println(ActivityManager.supportsSplitScreenMultiWindow()); + pw.println(ActivityManager.supportsSplitScreenMultiWindow(mInternal.mContext)); return 0; } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 5636e197aaee..9698a8fa91fd 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -130,6 +130,7 @@ import android.content.pm.ApplicationInfo; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.GraphicBuffer; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; @@ -1419,19 +1420,17 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo break; case ANIM_THUMBNAIL_SCALE_UP: case ANIM_THUMBNAIL_SCALE_DOWN: - boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP); - service.mWindowManager.overridePendingAppTransitionThumb( - pendingOptions.getThumbnail(), + final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP); + final GraphicBuffer buffer = pendingOptions.getThumbnail(); + service.mWindowManager.overridePendingAppTransitionThumb(buffer, pendingOptions.getStartX(), pendingOptions.getStartY(), pendingOptions.getOnAnimationStartListener(), scaleUp); if (intent.getSourceBounds() == null) { intent.setSourceBounds(new Rect(pendingOptions.getStartX(), pendingOptions.getStartY(), - pendingOptions.getStartX() - + pendingOptions.getThumbnail().getWidth(), - pendingOptions.getStartY() - + pendingOptions.getThumbnail().getHeight())); + pendingOptions.getStartX() + buffer.getWidth(), + pendingOptions.getStartY() + buffer.getHeight())); } break; case ANIM_THUMBNAIL_ASPECT_SCALE_UP: diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 93e1ab462945..9db957c427f0 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -244,7 +244,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai static final int REMOVE_TASK_MODE_MOVING = 1; // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new // stack and the new stack will be on top of all stacks. - private static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2; + static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2; // The height/width divide used when fitting a task within a bounds with method // {@link #fitWithinBounds}. diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index e180aefcd11a..e828d38ef249 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2989,8 +2989,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Calculate the default bounds (don't use existing stack bounds as we may have just created // the stack, and schedule the start of the animation into PiP (the bounds animator that // is triggered by this is posted on another thread) - final Rect destBounds = stack.getPictureInPictureBounds(aspectRatio, - false /* useExistingStackBounds */); + final Rect destBounds = stack.getDefaultPictureInPictureBounds(aspectRatio); + stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */, true /* fromFullscreen */); diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 7ed07e0e931a..07caf9e5611a 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1432,7 +1432,13 @@ class ActivityStarter { + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent); mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; mNewTaskInfo = mSourceRecord.info; - mNewTaskIntent = mSourceRecord.getTask().intent; + + // It is not guaranteed that the source record will have a task associated with it. For, + // example, if this method is being called for processing a pending activity launch, it + // is possible that the activity has been removed from the task after the launch was + // enqueued. + final TaskRecord sourceTask = mSourceRecord.getTask(); + mNewTaskIntent = sourceTask != null ? sourceTask.intent : null; } mSourceRecord = null; mSourceStack = null; diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 243906260593..c20221bfe4aa 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -17,6 +17,8 @@ package com.android.server.am; import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU; +import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO; +import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI; import android.annotation.Nullable; import android.bluetooth.BluetoothActivityEnergyInfo; @@ -87,6 +89,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub implements PowerManagerInternal.LowPowerModeListener, BatteryStatsImpl.PlatformIdleStateCallback { static final String TAG = "BatteryStatsService"; + static final boolean DBG = false; /** * How long to wait on an individual subsystem to return its stats. @@ -152,11 +155,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub case MSG_WRITE_TO_DISK: updateExternalStatsSync("write", UPDATE_ALL); - Slog.d(TAG, "begin writeAsyncLocked"); + if (DBG) Slog.d(TAG, "begin writeAsyncLocked"); synchronized (mStats) { mStats.writeAsyncLocked(); } - Slog.d(TAG, "end writeAsyncLocked"); + if (DBG) Slog.d(TAG, "end writeAsyncLocked"); break; } } @@ -196,7 +199,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public String getPlatformLowPowerStats() { - Slog.d(TAG, "begin getPlatformLowPowerStats"); + if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats"); try { mUtf8BufferStat.clear(); mUtf16BufferStat.clear(); @@ -212,7 +215,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub mUtf16BufferStat.flip(); return mUtf16BufferStat.toString(); } finally { - Slog.d(TAG, "end getPlatformLowPowerStats"); + if (DBG) Slog.d(TAG, "end getPlatformLowPowerStats"); } } @@ -230,10 +233,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void publish(Context context) { mContext = context; - mStats.setRadioScanningTimeout(mContext.getResources().getInteger( - com.android.internal.R.integer.config_radioScanningTimeout) - * 1000L); - mStats.setPowerProfile(new PowerProfile(context)); + synchronized (mStats) { + mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger( + com.android.internal.R.integer.config_radioScanningTimeout) + * 1000L); + mStats.setPowerProfileLocked(new PowerProfile(context)); + } ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder()); } @@ -244,9 +249,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void initPowerManagement() { final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class); powerMgr.registerLowPowerModeObserver(this); - mStats.notePowerSaveMode( - powerMgr.getLowPowerState(ServiceType.BATTERY_STATS) - .batterySaverEnabled); + synchronized (mStats) { + mStats.notePowerSaveModeLocked( + powerMgr.getLowPowerState(ServiceType.BATTERY_STATS) + .batterySaverEnabled); + } (new WakeupReasonThread()).start(); } @@ -279,7 +286,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public void onLowPowerModeChanged(PowerSaveState result) { synchronized (mStats) { - mStats.notePowerSaveMode(result.batterySaverEnabled); + mStats.notePowerSaveModeLocked(result.batterySaverEnabled); } } @@ -561,11 +568,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void noteScreenState(int state) { enforceCallingPermission(); - Slog.d(TAG, "begin noteScreenState"); + if (DBG) Slog.d(TAG, "begin noteScreenState"); synchronized (mStats) { mStats.noteScreenStateLocked(state); } - Slog.d(TAG, "end noteScreenState"); + if (DBG) Slog.d(TAG, "end noteScreenState"); } public void noteScreenBrightness(int brightness) { @@ -605,8 +612,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) { enforceCallingPermission(); + boolean update; synchronized (mStats) { - mStats.noteMobileRadioPowerState(powerState, timestampNs, uid); + update = mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid); + } + + if (update) { + mHandler.scheduleSync("modem-data", UPDATE_RADIO); } } @@ -718,11 +730,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void noteStartCamera(int uid) { enforceCallingPermission(); - Slog.d(TAG, "begin noteStartCamera"); + if (DBG) Slog.d(TAG, "begin noteStartCamera"); synchronized (mStats) { mStats.noteCameraOnLocked(uid); } - Slog.d(TAG, "end noteStartCamera"); + if (DBG) Slog.d(TAG, "end noteStartCamera"); } public void noteStopCamera(int uid) { @@ -758,7 +770,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active" : "inactive"; mHandler.scheduleSync("wifi-data: " + type, - BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI); + UPDATE_WIFI); } mStats.noteWifiRadioPowerState(powerState, tsNanos, uid); } @@ -916,9 +928,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public void noteNetworkStatsEnabled() { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteNetworkStatsEnabledLocked(); - } + mHandler.scheduleSync("network-stats-enabled", UPDATE_RADIO | UPDATE_WIFI); } @Override @@ -944,10 +954,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub } @Override - public void noteBleScanStarted(WorkSource ws) { + public void noteBleScanStarted(WorkSource ws, boolean isUnoptimized) { enforceCallingPermission(); synchronized (mStats) { - mStats.noteBluetoothScanStartedFromSourceLocked(ws); + mStats.noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized); } } @@ -984,9 +994,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub return; } - synchronized (mStats) { - mStats.updateWifiStateLocked(info); - } + mStats.updateWifiState(info); } @Override @@ -1011,9 +1019,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub return; } - synchronized (mStats) { - mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), info); - } + mStats.updateMobileRadioState(info); } public boolean isOnBattery() { @@ -1342,23 +1348,23 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } } - Slog.d(TAG, "begin dumpCheckinLocked from UID " + Binder.getCallingUid()); + if (DBG) Slog.d(TAG, "begin dumpCheckinLocked from UID " + Binder.getCallingUid()); synchronized (mStats) { mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); if (writeData) { mStats.writeAsyncLocked(); } } - Slog.d(TAG, "end dumpCheckinLocked"); + if (DBG) Slog.d(TAG, "end dumpCheckinLocked"); } else { - Slog.d(TAG, "begin dumpLocked from UID " + Binder.getCallingUid()); + if (DBG) Slog.d(TAG, "begin dumpLocked from UID " + Binder.getCallingUid()); synchronized (mStats) { mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); if (writeData) { mStats.writeAsyncLocked(); } } - Slog.d(TAG, "end dumpLocked"); + if (DBG) Slog.d(TAG, "end dumpLocked"); } } @@ -1480,15 +1486,15 @@ public final class BatteryStatsService extends IBatteryStats.Stub SynchronousResultReceiver bluetoothReceiver = null; SynchronousResultReceiver modemReceiver = null; - Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason); + if (DBG) Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason); synchronized (mExternalStatsLock) { if (mContext == null) { // Don't do any work yet. - Slog.d(TAG, "end updateExternalStatsSync"); + if (DBG) Slog.d(TAG, "end updateExternalStatsSync"); return; } - if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) { + if ((updateFlags & UPDATE_WIFI) != 0) { if (mWifiManager == null) { mWifiManager = IWifiManager.Stub.asInterface( ServiceManager.getService(Context.WIFI_SERVICE)); @@ -1557,14 +1563,6 @@ public final class BatteryStatsService extends IBatteryStats.Stub mStats.updateKernelWakelocksLocked(); mStats.updateKernelMemoryBandwidthLocked(); - if (wifiInfo != null) { - if (wifiInfo.isValid()) { - mStats.updateWifiStateLocked(extractDelta(wifiInfo)); - } else { - Slog.e(TAG, "wifi info is invalid: " + wifiInfo); - } - } - if (bluetoothInfo != null) { if (bluetoothInfo.isValid()) { mStats.updateBluetoothStateLocked(bluetoothInfo); @@ -1572,18 +1570,25 @@ public final class BatteryStatsService extends IBatteryStats.Stub Slog.e(TAG, "bluetooth info is invalid: " + bluetoothInfo); } } + } - if (modemInfo != null) { - if (modemInfo.isValid()) { - mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), - modemInfo); - } else { - Slog.e(TAG, "modem info is invalid: " + modemInfo); - } + if (wifiInfo != null) { + if (wifiInfo.isValid()) { + mStats.updateWifiState(extractDelta(wifiInfo)); + } else { + Slog.e(TAG, "wifi info is invalid: " + wifiInfo); + } + } + + if (modemInfo != null) { + if (modemInfo.isValid()) { + mStats.updateMobileRadioState(modemInfo); + } else { + Slog.e(TAG, "modem info is invalid: " + modemInfo); } } } - Slog.d(TAG, "end updateExternalStatsSync"); + if (DBG) Slog.d(TAG, "end updateExternalStatsSync"); } /** @@ -1603,7 +1608,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub return getHealthStatsForUidLocked(requestUid); } } catch (Exception ex) { - Slog.d(TAG, "Crashed while writing for takeUidSnapshot(" + requestUid + ")", ex); + Slog.w(TAG, "Crashed while writing for takeUidSnapshot(" + requestUid + ")", ex); throw ex; } finally { Binder.restoreCallingIdentity(ident); @@ -1633,7 +1638,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub return results; } } catch (Exception ex) { - Slog.d(TAG, "Crashed while writing for takeUidSnapshots(" + if (DBG) Slog.d(TAG, "Crashed while writing for takeUidSnapshots(" + Arrays.toString(requestUids) + ") i=" + i, ex); throw ex; } finally { diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index 144eb11cbf85..2e0ec0b361e2 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -97,7 +97,7 @@ class KeyguardController { mKeyguardShowing = showing; dismissDockedStackIfNeeded(); if (showing) { - mKeyguardGoingAway = false; + setKeyguardGoingAway(false); mDismissalRequested = false; } mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); @@ -114,7 +114,7 @@ class KeyguardController { if (mKeyguardShowing) { mWindowManager.deferSurfaceLayout(); try { - mKeyguardGoingAway = true; + setKeyguardGoingAway(true); mWindowManager.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */, convertTransitFlags(flags), false /* forceOverride */); @@ -139,6 +139,11 @@ class KeyguardController { mWindowManager.dismissKeyguard(callback); } + private void setKeyguardGoingAway(boolean keyguardGoingAway) { + mKeyguardGoingAway = keyguardGoingAway; + mWindowManager.setKeyguardGoingAway(keyguardGoingAway); + } + private void failCallback(IKeyguardDismissCallback callback) { try { callback.onDismissError(); diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java index 702bf92c65f8..2010c24000e8 100644 --- a/services/core/java/com/android/server/am/PinnedActivityStack.java +++ b/services/core/java/com/android/server/am/PinnedActivityStack.java @@ -44,9 +44,9 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds); } - Rect getPictureInPictureBounds(float aspectRatio, boolean useExistingStackBounds) { + Rect getDefaultPictureInPictureBounds(float aspectRatio) { return getWindowContainerController().getPictureInPictureBounds(aspectRatio, - useExistingStackBounds); + null /* currentStackBounds */); } void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration, diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java index deb3b287d7aa..39aed7cf3d67 100644 --- a/services/core/java/com/android/server/am/ProcessStatsService.java +++ b/services/core/java/com/android/server/am/ProcessStatsService.java @@ -233,7 +233,8 @@ public final class ProcessStatsService extends IProcessStats.Stub { updateFile(); } mLastWriteTime = SystemClock.uptimeMillis(); - Slog.i(TAG, "Prepared write state in " + (SystemClock.uptimeMillis()-now) + "ms"); + if (DEBUG) Slog.d(TAG, "Prepared write state in " + + (SystemClock.uptimeMillis()-now) + "ms"); if (!sync) { BackgroundThread.getHandler().post(new Runnable() { @Override public void run() { diff --git a/services/core/java/com/android/server/am/ProviderMap.java b/services/core/java/com/android/server/am/ProviderMap.java index a6997f944a4c..32d03daedef3 100644 --- a/services/core/java/com/android/server/am/ProviderMap.java +++ b/services/core/java/com/android/server/am/ProviderMap.java @@ -382,18 +382,29 @@ public final class ProviderMap { } /** - * Invokes IApplicationThread.dumpProvider() on the thread of the specified provider if - * there is a thread associated with the provider. + * Before invoking IApplicationThread.dumpProvider(), print meta information to the print + * writer and handle passed flags. */ private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw, final ContentProviderRecord r, String[] args, boolean dumpAll) { + for (String s: args) { + if (!dumpAll && s.contains("--proto")) { + if (r.proc != null && r.proc.thread != null) { + dumpToTransferPipe(null , fd, pw, r, args); + } + return; + } + } String innerPrefix = prefix + " "; synchronized (mAm) { pw.print(prefix); pw.print("PROVIDER "); - pw.print(r); - pw.print(" pid="); - if (r.proc != null) pw.println(r.proc.pid); - else pw.println("(not running)"); + pw.print(r); + pw.print(" pid="); + if (r.proc != null) { + pw.println(r.proc.pid); + } else { + pw.println("(not running)"); + } if (dumpAll) { r.dump(pw, innerPrefix, true); } @@ -401,23 +412,32 @@ public final class ProviderMap { if (r.proc != null && r.proc.thread != null) { pw.println(" Client:"); pw.flush(); + dumpToTransferPipe(" ", fd, pw, r, args); + } + } + + /** + * Invokes IApplicationThread.dumpProvider() on the thread of the specified provider without + * any meta string (e.g., provider info, indentation) written to the file descriptor. + */ + private void dumpToTransferPipe(String prefix, FileDescriptor fd, PrintWriter pw, + final ContentProviderRecord r, String[] args) { + try { + TransferPipe tp = new TransferPipe(); try { - TransferPipe tp = new TransferPipe(); - try { - r.proc.thread.dumpProvider( - tp.getWriteFd(), r.provider.asBinder(), args); - tp.setBufferPrefix(" "); - // Short timeout, since blocking here can - // deadlock with the application. - tp.go(fd, 2000); - } finally { - tp.kill(); - } - } catch (IOException ex) { - pw.println(" Failure while dumping the provider: " + ex); - } catch (RemoteException ex) { - pw.println(" Got a RemoteException while dumping the service"); + r.proc.thread.dumpProvider( + tp.getWriteFd(), r.provider.asBinder(), args); + tp.setBufferPrefix(prefix); + // Short timeout, since blocking here can + // deadlock with the application. + tp.go(fd, 2000); + } finally { + tp.kill(); } + } catch (IOException ex) { + pw.println(" Failure while dumping the provider: " + ex); + } catch (RemoteException ex) { + pw.println(" Got a RemoteException while dumping the service"); } } } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 7eec945a6cbb..e81e6d7334b3 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -115,6 +115,7 @@ import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING; +import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP; import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY; import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; @@ -673,8 +674,11 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta mWindowContainerController.reparent(toStack.getWindowContainerController(), position, moveStackMode == REPARENT_MOVE_STACK_TO_FRONT); + final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT + || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront)); // Move the task - sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING); + sourceStack.removeTask(this, reason, moveStackToFront + ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING); toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason); if (schedulePictureInPictureModeChange) { @@ -693,8 +697,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta // If the task had focus before (or we're requested to move focus), move focus to the // new stack by moving the stack to the front. - final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT - || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront)); if (r != null) { toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed, wasPaused, reason); diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index b8d633fc666f..73a365b0da72 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -221,7 +221,9 @@ abstract public class ManagedServices { restoredSettingName(element), newValue, userid); - updateSettingsAccordingToInstalledServices(element, userid); + if (mConfig.secureSettingName.equals(element)) { + updateSettingsAccordingToInstalledServices(element, userid); + } rebuildRestoredPackages(); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index e377d57a0ead..3667e161b7af 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -3225,7 +3225,7 @@ public class NotificationManagerService extends SystemService { Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled) != 0; if (warningEnabled) { Toast toast = Toast.makeText(getContext(), mHandler.getLooper(), toastText, - Toast.LENGTH_LONG); + Toast.LENGTH_SHORT); toast.show(); } } @@ -3759,13 +3759,7 @@ public class NotificationManagerService extends SystemService { return true; } if (record.sbn.isGroup()) { - if (notification.isGroupSummary() - && notification.getGroupAlertBehavior() == Notification.GROUP_ALERT_CHILDREN) { - return true; - } else if (notification.isGroupChild() - && notification.getGroupAlertBehavior() == Notification.GROUP_ALERT_SUMMARY) { - return true; - } + return notification.suppressAlertingDueToGrouping(); } return false; } diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index e6e461744094..c95b5c557b32 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -395,10 +395,11 @@ public class Installer extends SystemService { } } - public void freeCache(String uuid, long freeStorageSize, int flags) throws InstallerException { + public void freeCache(String uuid, long targetFreeBytes, long cacheReservedBytes, int flags) + throws InstallerException { if (!checkBeforeRemote()) return; try { - mInstalld.freeCache(uuid, freeStorageSize, flags); + mInstalld.freeCache(uuid, targetFreeBytes, cacheReservedBytes, flags); } catch (Exception e) { throw InstallerException.from(e); } diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java index b1659841d5ac..211a1c9f3edf 100644 --- a/services/core/java/com/android/server/pm/InstantAppRegistry.java +++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.Intent; import android.content.pm.InstantAppInfo; +import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -32,6 +33,8 @@ import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.UserHandle; +import android.os.storage.StorageManager; import android.provider.Settings; import android.util.ArrayMap; import android.util.AtomicFile; @@ -76,7 +79,16 @@ class InstantAppRegistry { private static final String LOG_TAG = "InstantAppRegistry"; - private static final long DEFAULT_UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS = + static final long DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD = + DEBUG ? 30 * 1000L /* thirty seconds */ : 7 * 24 * 60 * 60 * 1000L; /* one week */ + + private static final long DEFAULT_INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD = + DEBUG ? 60 * 1000L /* one min */ : 6 * 30 * 24 * 60 * 60 * 1000L; /* six months */ + + static final long DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD = + DEBUG ? 30 * 1000L /* thirty seconds */ : 7 * 24 * 60 * 60 * 1000L; /* one week */ + + private static final long DEFAULT_UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD = DEBUG ? 60 * 1000L /* one min */ : 6 * 30 * 24 * 60 * 60 * 1000L; /* six months */ private static final String INSTANT_APPS_FOLDER = "instant"; @@ -535,46 +547,195 @@ class InstantAppRegistry { } } - public void pruneInstantAppsLPw() { - // For now we prune only state for uninstalled instant apps - final long maxCacheDurationMillis = Settings.Global.getLong( + void pruneInstantApps() { + final long maxInstalledCacheDuration = Settings.Global.getLong( mService.mContext.getContentResolver(), - Settings.Global.UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS, - DEFAULT_UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS); - - for (int userId : UserManagerService.getInstance().getUserIds()) { - // Prune in-memory state - removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) -> { - final long elapsedCachingMillis = System.currentTimeMillis() - state.mTimestamp; - return (elapsedCachingMillis > maxCacheDurationMillis); - }, userId); - - // Prune on-disk state - File instantAppsDir = getInstantApplicationsDir(userId); - if (!instantAppsDir.exists()) { - continue; + Settings.Global.INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD, + DEFAULT_INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD); + + final long maxUninstalledCacheDuration = Settings.Global.getLong( + mService.mContext.getContentResolver(), + Settings.Global.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD, + DEFAULT_UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD); + + try { + pruneInstantApps(Long.MAX_VALUE, + maxInstalledCacheDuration, maxUninstalledCacheDuration); + } catch (IOException e) { + Slog.e(LOG_TAG, "Error pruning installed and uninstalled instant apps", e); + } + } + + boolean pruneInstalledInstantApps(long neededSpace, long maxInstalledCacheDuration) { + try { + return pruneInstantApps(neededSpace, maxInstalledCacheDuration, Long.MAX_VALUE); + } catch (IOException e) { + Slog.e(LOG_TAG, "Error pruning installed instant apps", e); + return false; + } + } + + boolean pruneUninstalledInstantApps(long neededSpace, long maxUninstalledCacheDuration) { + try { + return pruneInstantApps(neededSpace, Long.MAX_VALUE, maxUninstalledCacheDuration); + } catch (IOException e) { + Slog.e(LOG_TAG, "Error pruning uninstalled instant apps", e); + return false; + } + } + + /** + * Prunes instant apps until there is enough <code>neededSpace</code>. Both + * installed and uninstalled instant apps are pruned that are older than + * <code>maxInstalledCacheDuration</code> and <code>maxUninstalledCacheDuration</code> + * respectively. All times are in milliseconds. + * + * @param neededSpace The space to ensure is free. + * @param maxInstalledCacheDuration The max duration for caching installed apps in millis. + * @param maxUninstalledCacheDuration The max duration for caching uninstalled apps in millis. + * @return Whether enough space was freed. + * + * @throws IOException + */ + private boolean pruneInstantApps(long neededSpace, long maxInstalledCacheDuration, + long maxUninstalledCacheDuration) throws IOException { + final StorageManager storage = mService.mContext.getSystemService(StorageManager.class); + final File file = storage.findPathForUuid(StorageManager.UUID_PRIVATE_INTERNAL); + + if (file.getUsableSpace() >= neededSpace) { + return true; + } + + List<String> packagesToDelete = null; + + final int[] allUsers; + final long now = System.currentTimeMillis(); + + // Prune first installed instant apps + synchronized (mService.mPackages) { + allUsers = PackageManagerService.sUserManager.getUserIds(); + + final int packageCount = mService.mPackages.size(); + for (int i = 0; i < packageCount; i++) { + final PackageParser.Package pkg = mService.mPackages.valueAt(i); + if (now - pkg.getLatestPackageUseTimeInMills() < maxInstalledCacheDuration) { + continue; + } + if (!(pkg.mExtras instanceof PackageSetting)) { + continue; + } + final PackageSetting ps = (PackageSetting) pkg.mExtras; + boolean installedOnlyAsInstantApp = false; + for (int userId : allUsers) { + if (ps.getInstalled(userId)) { + if (ps.getInstantApp(userId)) { + installedOnlyAsInstantApp = true; + } else { + installedOnlyAsInstantApp = false; + break; + } + } + } + if (installedOnlyAsInstantApp) { + if (packagesToDelete == null) { + packagesToDelete = new ArrayList<>(); + } + packagesToDelete.add(pkg.packageName); + } } - File[] files = instantAppsDir.listFiles(); - if (files == null) { - continue; + + if (packagesToDelete != null) { + packagesToDelete.sort((String lhs, String rhs) -> { + final PackageParser.Package lhsPkg = mService.mPackages.get(lhs); + final PackageParser.Package rhsPkg = mService.mPackages.get(rhs); + if (lhsPkg == null && rhsPkg == null) { + return 0; + } else if (lhsPkg == null) { + return -1; + } else if (rhsPkg == null) { + return 1; + } else { + if (lhsPkg.getLatestPackageUseTimeInMills() > + rhsPkg.getLatestPackageUseTimeInMills()) { + return 1; + } else if (lhsPkg.getLatestPackageUseTimeInMills() < + rhsPkg.getLatestPackageUseTimeInMills()) { + return -1; + } else { + if (lhsPkg.mExtras instanceof PackageSetting + && rhsPkg.mExtras instanceof PackageSetting) { + final PackageSetting lhsPs = (PackageSetting) lhsPkg.mExtras; + final PackageSetting rhsPs = (PackageSetting) rhsPkg.mExtras; + if (lhsPs.firstInstallTime > rhsPs.firstInstallTime) { + return 1; + } else { + return -1; + } + } else { + return 0; + } + } + } + }); } - for (File instantDir : files) { - if (!instantDir.isDirectory()) { - continue; + } + + if (packagesToDelete != null) { + final int packageCount = packagesToDelete.size(); + for (int i = 0; i < packageCount; i++) { + final String packageToDelete = packagesToDelete.get(i); + if (mService.deletePackageX(packageToDelete, PackageManager.VERSION_CODE_HIGHEST, + UserHandle.USER_SYSTEM, PackageManager.DELETE_ALL_USERS) + == PackageManager.DELETE_SUCCEEDED) { + if (file.getUsableSpace() >= neededSpace) { + return true; + } } + } + } - File metadataFile = new File(instantDir, INSTANT_APP_METADATA_FILE); - if (!metadataFile.exists()) { + // Prune uninstalled instant apps + synchronized (mService.mPackages) { + // TODO: Track last used time for uninstalled instant apps for better pruning + for (int userId : UserManagerService.getInstance().getUserIds()) { + // Prune in-memory state + removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) -> { + final long elapsedCachingMillis = System.currentTimeMillis() - state.mTimestamp; + return (elapsedCachingMillis > maxUninstalledCacheDuration); + }, userId); + + // Prune on-disk state + File instantAppsDir = getInstantApplicationsDir(userId); + if (!instantAppsDir.exists()) { + continue; + } + File[] files = instantAppsDir.listFiles(); + if (files == null) { continue; } + for (File instantDir : files) { + if (!instantDir.isDirectory()) { + continue; + } + + File metadataFile = new File(instantDir, INSTANT_APP_METADATA_FILE); + if (!metadataFile.exists()) { + continue; + } - final long elapsedCachingMillis = System.currentTimeMillis() - - metadataFile.lastModified(); - if (elapsedCachingMillis > maxCacheDurationMillis) { - deleteDir(instantDir); + final long elapsedCachingMillis = System.currentTimeMillis() + - metadataFile.lastModified(); + if (elapsedCachingMillis > maxUninstalledCacheDuration) { + deleteDir(instantDir); + if (file.getUsableSpace() >= neededSpace) { + return true; + } + } } } } + + return false; } private @Nullable List<InstantAppInfo> getInstalledInstantApplicationsLPr( diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 782325a941b9..99eda862473b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -875,9 +875,9 @@ public class PackageManagerService extends IPackageManager.Stub new ParallelPackageParserCallback(); public static final class SharedLibraryEntry { - public final String path; - public final String apk; - public final SharedLibraryInfo info; + public final @Nullable String path; + public final @Nullable String apk; + public final @NonNull SharedLibraryInfo info; SharedLibraryEntry(String _path, String _apk, String name, int version, int type, String declaringPackageName, int declaringPackageVersionCode) { @@ -1312,6 +1312,9 @@ public class PackageManagerService extends IPackageManager.Stub // Delay time in millisecs static final int BROADCAST_DELAY = 10 * 1000; + private static final long DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD = + 2 * 60 * 60 * 1000L; /* two hours */ + static UserManagerService sUserManager; // Stores a list of users whose package restrictions file needs to be updated @@ -4155,13 +4158,13 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void freeStorageAndNotify(final String volumeUuid, final long freeStorageSize, - final IPackageDataObserver observer) { + final int storageFlags, final IPackageDataObserver observer) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CLEAR_APP_CACHE, null); mHandler.post(() -> { boolean success = false; try { - freeStorage(volumeUuid, freeStorageSize, 0); + freeStorage(volumeUuid, freeStorageSize, storageFlags); success = true; } catch (IOException e) { Slog.w(TAG, e); @@ -4178,13 +4181,13 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void freeStorage(final String volumeUuid, final long freeStorageSize, - final IntentSender pi) { + final int storageFlags, final IntentSender pi) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CLEAR_APP_CACHE, TAG); mHandler.post(() -> { boolean success = false; try { - freeStorage(volumeUuid, freeStorageSize, 0); + freeStorage(volumeUuid, freeStorageSize, storageFlags); success = true; } catch (IOException e) { Slog.w(TAG, e); @@ -4209,10 +4212,14 @@ public class PackageManagerService extends IPackageManager.Stub if (file.getUsableSpace() >= bytes) return; if (ENABLE_FREE_CACHE_V2) { - final boolean aggressive = (storageFlags - & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0; final boolean internalVolume = Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid); + final boolean aggressive = (storageFlags + & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0; + final boolean defyReserved = (storageFlags + & StorageManager.FLAG_ALLOCATE_DEFY_RESERVED) != 0; + final long reservedBytes = (aggressive || defyReserved) ? 0 + : storage.getStorageCacheBytes(file); // 1. Pre-flight to determine if we have any chance to succeed // 2. Consider preloaded data (after 1w honeymoon, unless aggressive) @@ -4230,29 +4237,52 @@ public class PackageManagerService extends IPackageManager.Stub // 4. Consider cached app data (above quotas) try { - mInstaller.freeCache(volumeUuid, bytes, Installer.FLAG_FREE_CACHE_V2); + mInstaller.freeCache(volumeUuid, bytes, reservedBytes, + Installer.FLAG_FREE_CACHE_V2); } catch (InstallerException ignored) { } if (file.getUsableSpace() >= bytes) return; - // 5. Consider shared libraries with refcount=0 and age>2h + // 5. Consider shared libraries with refcount=0 and age>min cache period + if (internalVolume && pruneUnusedStaticSharedLibraries(bytes, + android.provider.Settings.Global.getLong(mContext.getContentResolver(), + Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD, + DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD))) { + return; + } + // 6. Consider dexopt output (aggressive only) - // 7. Consider ephemeral apps not used in last week + // TODO: Implement + + // 7. Consider installed instant apps unused longer than min cache period + if (internalVolume && mInstantAppRegistry.pruneInstalledInstantApps(bytes, + android.provider.Settings.Global.getLong(mContext.getContentResolver(), + Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, + InstantAppRegistry.DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) { + return; + } // 8. Consider cached app data (below quotas) try { - mInstaller.freeCache(volumeUuid, bytes, Installer.FLAG_FREE_CACHE_V2 - | Installer.FLAG_FREE_CACHE_V2_DEFY_QUOTA); + mInstaller.freeCache(volumeUuid, bytes, reservedBytes, + Installer.FLAG_FREE_CACHE_V2 | Installer.FLAG_FREE_CACHE_V2_DEFY_QUOTA); } catch (InstallerException ignored) { } if (file.getUsableSpace() >= bytes) return; // 9. Consider DropBox entries - // 10. Consider ephemeral cookies + // TODO: Implement + // 10. Consider instant meta-data (uninstalled apps) older that min cache period + if (internalVolume && mInstantAppRegistry.pruneUninstalledInstantApps(bytes, + android.provider.Settings.Global.getLong(mContext.getContentResolver(), + Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD, + InstantAppRegistry.DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) { + return; + } } else { try { - mInstaller.freeCache(volumeUuid, bytes, 0); + mInstaller.freeCache(volumeUuid, bytes, 0, 0); } catch (InstallerException ignored) { } if (file.getUsableSpace() >= bytes) return; @@ -4261,6 +4291,69 @@ public class PackageManagerService extends IPackageManager.Stub throw new IOException("Failed to free " + bytes + " on storage device at " + file); } + private boolean pruneUnusedStaticSharedLibraries(long neededSpace, long maxCachePeriod) + throws IOException { + final StorageManager storage = mContext.getSystemService(StorageManager.class); + final File volume = storage.findPathForUuid(StorageManager.UUID_PRIVATE_INTERNAL); + + List<VersionedPackage> packagesToDelete = null; + final long now = System.currentTimeMillis(); + + synchronized (mPackages) { + final int[] allUsers = sUserManager.getUserIds(); + final int libCount = mSharedLibraries.size(); + for (int i = 0; i < libCount; i++) { + final SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i); + if (versionedLib == null) { + continue; + } + final int versionCount = versionedLib.size(); + for (int j = 0; j < versionCount; j++) { + SharedLibraryInfo libInfo = versionedLib.valueAt(j).info; + // Skip packages that are not static shared libs. + if (!libInfo.isStatic()) { + break; + } + // Important: We skip static shared libs used for some user since + // in such a case we need to keep the APK on the device. The check for + // a lib being used for any user is performed by the uninstall call. + final VersionedPackage declaringPackage = libInfo.getDeclaringPackage(); + // Resolve the package name - we use synthetic package names internally + final String internalPackageName = resolveInternalPackageNameLPr( + declaringPackage.getPackageName(), declaringPackage.getVersionCode()); + final PackageSetting ps = mSettings.getPackageLPr(internalPackageName); + // Skip unused static shared libs cached less than the min period + // to prevent pruning a lib needed by a subsequently installed package. + if (ps == null || now - ps.lastUpdateTime < maxCachePeriod) { + continue; + } + if (packagesToDelete == null) { + packagesToDelete = new ArrayList<>(); + } + packagesToDelete.add(new VersionedPackage(internalPackageName, + declaringPackage.getVersionCode())); + } + } + } + + if (packagesToDelete != null) { + final int packageCount = packagesToDelete.size(); + for (int i = 0; i < packageCount; i++) { + final VersionedPackage pkgToDelete = packagesToDelete.get(i); + // Delete the package synchronously (will fail of the lib used for any user). + if (deletePackageX(pkgToDelete.getPackageName(), pkgToDelete.getVersionCode(), + UserHandle.USER_SYSTEM, PackageManager.DELETE_ALL_USERS) + == PackageManager.DELETE_SUCCEEDED) { + if (volume.getUsableSpace() >= neededSpace) { + return true; + } + } + } + } + + return false; + } + /** * Update given flags based on encryption status of current user. */ @@ -10650,8 +10743,7 @@ public class PackageManagerService extends IPackageManager.Stub final int versionCount = versionedLib.size(); for (int i = 0; i < versionCount; i++) { SharedLibraryInfo libInfo = versionedLib.valueAt(i).info; - // TODO: We will change version code to long, so in the new API it is long - final int libVersionCode = (int) libInfo.getDeclaringPackage() + final int libVersionCode = libInfo.getDeclaringPackage() .getVersionCode(); if (libInfo.getVersion() < pkg.staticSharedLibVersion) { minVersionCode = Math.max(minVersionCode, libVersionCode + 1); @@ -15494,7 +15586,7 @@ public class PackageManagerService extends IPackageManager.Stub origin.resolvedPath, isForwardLocked(), packageAbiOverride); try { - mInstaller.freeCache(null, sizeBytes + lowThreshold, 0); + mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0); pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags, packageAbiOverride); } catch (InstallerException e) { @@ -18488,7 +18580,7 @@ public class PackageManagerService extends IPackageManager.Stub * persisting settings for later use * sending a broadcast if necessary */ - private int deletePackageX(String packageName, int versionCode, int userId, int deleteFlags) { + int deletePackageX(String packageName, int versionCode, int userId, int deleteFlags) { final PackageRemovedInfo info = new PackageRemovedInfo(this); final boolean res; @@ -18531,7 +18623,7 @@ public class PackageManagerService extends IPackageManager.Stub pkg.staticSharedLibVersion); if (libEntry != null) { for (int currUserId : allUsers) { - if (userId != UserHandle.USER_ALL && userId != currUserId) { + if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) { continue; } List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr( @@ -24273,9 +24365,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); @Override public void pruneInstantApps() { - synchronized (mPackages) { - mInstantAppRegistry.pruneInstantAppsLPw(); - } + mInstantAppRegistry.pruneInstantApps(); } @Override diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 908e51711b11..e3bc91971b06 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -60,7 +60,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_ST import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; @@ -1128,16 +1127,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); + final boolean keyguardGoingAway = mWindowManagerInternal.isKeyguardGoingAway(); + boolean disable = true; // Note: We postpone the rotating of the screen until the keyguard as well as the - // window manager have reported a draw complete. - if (mScreenOnEarly && mAwake && - mKeyguardDrawComplete && mWindowManagerDrawComplete) { + // window manager have reported a draw complete or the keyguard is going away in dismiss + // mode. + if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete) + || keyguardGoingAway)) { if (needSensorRunningLp()) { disable = false; //enable listener if not already enabled if (!mOrientationSensorEnabled) { - mOrientationListener.enable(); + // Don't clear the current sensor orientation if the keyguard is going away in + // dismiss mode. This allows window manager to use the last sensor reading to + // determine the orientation vs. falling back to the last known orientation if + // the sensor reading was cleared which can cause it to relaunch the app that + // will show in the wrong orientation first before correcting leading to app + // launch delays. + mOrientationListener.enable(!keyguardGoingAway /* clearCurrentRotation */); if(localLOGV) Slog.v(TAG, "Enabling listeners"); mOrientationSensorEnabled = true; } diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java index 8ef0acbd3808..64f64c0d45d6 100644 --- a/services/core/java/com/android/server/policy/WindowOrientationListener.java +++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java @@ -109,24 +109,37 @@ public abstract class WindowOrientationListener { * {@link #onProposedRotationChanged(int)} when the device orientation changes. */ public void enable() { + enable(true /* clearCurrentRotation */); + } + + /** + * Enables the WindowOrientationListener so it will monitor the sensor and call + * {@link #onProposedRotationChanged(int)} when the device orientation changes. + * + * @param clearCurrentRotation True if the current proposed sensor rotation should be cleared as + * part of the reset. + */ + public void enable(boolean clearCurrentRotation) { synchronized (mLock) { if (mSensor == null) { Slog.w(TAG, "Cannot detect sensors. Not enabled"); return; } - if (mEnabled == false) { - if (LOG) { - Slog.d(TAG, "WindowOrientationListener enabled"); - } - mOrientationJudge.resetLocked(); - if (mSensor.getType() == Sensor.TYPE_ACCELEROMETER) { - mSensorManager.registerListener( - mOrientationJudge, mSensor, mRate, DEFAULT_BATCH_LATENCY, mHandler); - } else { - mSensorManager.registerListener(mOrientationJudge, mSensor, mRate, mHandler); - } - mEnabled = true; + if (mEnabled) { + return; } + if (LOG) { + Slog.d(TAG, "WindowOrientationListener enabled clearCurrentRotation=" + + clearCurrentRotation); + } + mOrientationJudge.resetLocked(clearCurrentRotation); + if (mSensor.getType() == Sensor.TYPE_ACCELEROMETER) { + mSensorManager.registerListener( + mOrientationJudge, mSensor, mRate, DEFAULT_BATCH_LATENCY, mHandler); + } else { + mSensorManager.registerListener(mOrientationJudge, mSensor, mRate, mHandler); + } + mEnabled = true; } } @@ -278,8 +291,11 @@ public abstract class WindowOrientationListener { * Resets the state of the judge. * * Should only be called when holding WindowOrientationListener lock. + * + * @param clearCurrentRotation True if the current proposed sensor rotation should be + * cleared as part of the reset. */ - public abstract void resetLocked(); + public abstract void resetLocked(boolean clearCurrentRotation); /** * Dumps internal state of the orientation judge. @@ -602,7 +618,7 @@ public abstract class WindowOrientationListener { if (LOG) { Slog.v(TAG, "Resetting orientation listener."); } - resetLocked(); + resetLocked(true /* clearCurrentRotation */); skipSample = true; } else { final float alpha = timeDeltaMS / (FILTER_TIME_CONSTANT_MS + timeDeltaMS); @@ -778,9 +794,11 @@ public abstract class WindowOrientationListener { } @Override - public void resetLocked() { + public void resetLocked(boolean clearCurrentRotation) { mLastFilteredTimestampNanos = Long.MIN_VALUE; - mProposedRotation = -1; + if (clearCurrentRotation) { + mProposedRotation = -1; + } mFlatTimestampNanos = Long.MIN_VALUE; mFlat = false; mSwingTimestampNanos = Long.MIN_VALUE; @@ -1015,9 +1033,11 @@ public abstract class WindowOrientationListener { } @Override - public void resetLocked() { - mProposedRotation = -1; - mDesiredRotation = -1; + public void resetLocked(boolean clearCurrentRotation) { + if (clearCurrentRotation) { + mProposedRotation = -1; + mDesiredRotation = -1; + } mTouching = false; mTouchEndedTimestampNanos = Long.MIN_VALUE; unscheduleRotationEvaluationLocked(); diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java index 1b4eaf548809..da90e5adf4c4 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java @@ -30,7 +30,7 @@ import java.io.PrintWriter; */ public class KeyguardServiceDelegate { private static final String TAG = "KeyguardServiceDelegate"; - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; private static final int SCREEN_STATE_OFF = 0; private static final int SCREEN_STATE_TURNING_ON = 1; diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index ed98d1cbc5b2..3b5db29de9e0 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -87,6 +87,7 @@ import com.android.server.LockGuard; import com.android.server.RescueParty; import com.android.server.ServiceThread; import com.android.server.SystemService; +import com.android.server.UiThread; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; import com.android.server.lights.Light; @@ -2729,9 +2730,9 @@ public final class PowerManagerService extends SystemService }; // ShutdownThread must run on a looper capable of displaying the UI. - Message msg = Message.obtain(mHandler, runnable); + Message msg = Message.obtain(UiThread.getHandler(), runnable); msg.setAsynchronous(true); - mHandler.sendMessage(msg); + UiThread.getHandler().sendMessage(msg); // PowerManager.reboot() is documented not to return so just wait for the inevitable. if (wait) { diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java index fbc9e56fabf5..88b6d870afd7 100644 --- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java +++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java @@ -16,71 +16,60 @@ package com.android.server.storage; -import android.app.NotificationChannel; - -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.internal.notification.SystemNotificationChannels; -import com.android.internal.util.DumpUtils; -import com.android.server.EventLogTags; -import com.android.server.SystemService; -import com.android.server.pm.InstructionSets; +import android.annotation.WorkerThread; import android.app.Notification; +import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.pm.IPackageDataObserver; -import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.net.TrafficStats; import android.os.Binder; import android.os.Environment; import android.os.FileObserver; import android.os.Handler; import android.os.Message; -import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ShellCallback; import android.os.ShellCommand; -import android.os.StatFs; -import android.os.SystemClock; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.storage.StorageManager; -import android.provider.Settings; -import android.text.format.Formatter; -import android.util.EventLog; +import android.os.storage.VolumeInfo; +import android.text.format.DateUtils; +import android.util.ArrayMap; import android.util.Slog; -import android.util.TimeUtils; + +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; +import com.android.internal.notification.SystemNotificationChannels; +import com.android.internal.util.DumpUtils; +import com.android.internal.util.IndentingPrintWriter; +import com.android.server.EventLogTags; +import com.android.server.IoThread; +import com.android.server.SystemService; +import com.android.server.pm.InstructionSets; +import com.android.server.pm.PackageManagerService; + +import dalvik.system.VMRuntime; import java.io.File; import java.io.FileDescriptor; +import java.io.IOException; import java.io.PrintWriter; +import java.util.Objects; +import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; -import dalvik.system.VMRuntime; - /** - * This class implements a service to monitor the amount of disk - * storage space on the device. If the free storage on device is less - * than a tunable threshold value (a secure settings parameter; - * default 10%) a low memory notification is displayed to alert the - * user. If the user clicks on the low memory notification the - * Application Manager application gets launched to let the user free - * storage space. - * - * Event log events: A low memory event with the free storage on - * device in bytes is logged to the event log when the device goes low - * on storage space. The amount of free storage on the device is - * periodically logged to the event log. The log interval is a secure - * settings parameter with a default value of 12 hours. When the free - * storage differential goes below a threshold (again a secure - * settings parameter with a default value of 2MB), the free memory is - * logged to the event log. + * Service that monitors and maintains free space on storage volumes. + * <p> + * As the free space on a volume nears the threshold defined by + * {@link StorageManager#getStorageLowBytes(File)}, this service will clear out + * cached data to keep the disk from entering this low state. */ public class DeviceStorageMonitorService extends SystemService { - static final String TAG = "DeviceStorageMonitorService"; + private static final String TAG = "DeviceStorageMonitorService"; /** * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: @@ -88,68 +77,75 @@ public class DeviceStorageMonitorService extends SystemService { */ public static final String EXTRA_SEQUENCE = "seq"; - // TODO: extend to watch and manage caches on all private volumes + private static final int MSG_CHECK = 1; - static final boolean DEBUG = false; - static final boolean localLOGV = false; - - static final int DEVICE_MEMORY_WHAT = 1; - static final int FORCE_MEMORY_WHAT = 2; - private static final int MONITOR_INTERVAL = 1; //in minutes - - private static final int DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES = 12*60; //in minutes - private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB - private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000; + private static final long DEFAULT_LOG_DELTA_BYTES = 64 * TrafficStats.MB_IN_BYTES; + private static final long DEFAULT_CHECK_INTERVAL = DateUtils.MINUTE_IN_MILLIS; // com.android.internal.R.string.low_internal_storage_view_text_no_boot // hard codes 250MB in the message as the storage space required for the // boot image. - private static final long BOOT_IMAGE_STORAGE_REQUIREMENT = 250 * 1024 * 1024; - - private long mFreeMem; // on /data - private long mFreeMemAfterLastCacheClear; // on /data - private long mLastReportedFreeMem; - private long mLastReportedFreeMemTime; - boolean mLowMemFlag=false; - private boolean mMemFullFlag=false; - private final boolean mIsBootImageOnDisk; - private final ContentResolver mResolver; - private final long mTotalMemory; // on /data - private final StatFs mDataFileStats; - private final StatFs mSystemFileStats; - private final StatFs mCacheFileStats; - - private static final File DATA_PATH = Environment.getDataDirectory(); - private static final File SYSTEM_PATH = Environment.getRootDirectory(); - private static final File CACHE_PATH = Environment.getDownloadCacheDirectory(); - - private long mThreadStartTime = -1; - boolean mUpdatesStopped; - AtomicInteger mSeq = new AtomicInteger(1); - boolean mClearSucceeded = false; - boolean mClearingCache; - private final Intent mStorageLowIntent; - private final Intent mStorageOkIntent; - private final Intent mStorageFullIntent; - private final Intent mStorageNotFullIntent; - private CachePackageDataObserver mClearCacheObserver; + private static final long BOOT_IMAGE_STORAGE_REQUIREMENT = 250 * TrafficStats.MB_IN_BYTES; + + private NotificationManager mNotifManager; + + /** Sequence number used for testing */ + private final AtomicInteger mSeq = new AtomicInteger(1); + /** Forced level used for testing */ + private volatile int mForceLevel = State.LEVEL_UNKNOWN; + + /** Map from storage volume UUID to internal state */ + private final ArrayMap<UUID, State> mStates = new ArrayMap<>(); + + /** + * State for a specific storage volume, including the current "level" that + * we've alerted the user and apps about. + */ + private static class State { + private static final int LEVEL_UNKNOWN = -1; + private static final int LEVEL_NORMAL = 0; + private static final int LEVEL_LOW = 1; + private static final int LEVEL_FULL = 2; + + /** Last "level" that we alerted about */ + public int level = LEVEL_NORMAL; + /** Last {@link File#getUsableSpace()} that we logged about */ + public long lastUsableBytes = Long.MAX_VALUE; + + /** + * Test if the given level transition is "entering" a specific level. + * <p> + * As an example, a transition from {@link #LEVEL_NORMAL} to + * {@link #LEVEL_FULL} is considered to "enter" both {@link #LEVEL_LOW} + * and {@link #LEVEL_FULL}. + */ + private static boolean isEntering(int level, int oldLevel, int newLevel) { + return newLevel >= level && (oldLevel < level || oldLevel == LEVEL_UNKNOWN); + } + + /** + * Test if the given level transition is "leaving" a specific level. + * <p> + * As an example, a transition from {@link #LEVEL_FULL} to + * {@link #LEVEL_NORMAL} is considered to "leave" both + * {@link #LEVEL_FULL} and {@link #LEVEL_LOW}. + */ + private static boolean isLeaving(int level, int oldLevel, int newLevel) { + return newLevel < level && (oldLevel >= level || oldLevel == LEVEL_UNKNOWN); + } + + private static String levelToString(int level) { + switch (level) { + case State.LEVEL_UNKNOWN: return "UNKNOWN"; + case State.LEVEL_NORMAL: return "NORMAL"; + case State.LEVEL_LOW: return "LOW"; + case State.LEVEL_FULL: return "FULL"; + default: return Integer.toString(level); + } + } + } + private CacheFileDeletedObserver mCacheFileDeletedObserver; - private static final int _TRUE = 1; - private static final int _FALSE = 0; - // This is the raw threshold that has been set at which we consider - // storage to be low. - long mMemLowThreshold; - // This is the threshold at which we start trying to flush caches - // to get below the low threshold limit. It is less than the low - // threshold; we will allow storage to get a bit beyond the limit - // before flushing and checking if we are actually low. - private long mMemCacheStartTrimThreshold; - // This is the threshold that we try to get to when deleting cache - // files. This is greater than the low threshold so that we will flush - // more files than absolutely needed, to reduce the frequency that - // flushing takes place. - private long mMemCacheTrimToThreshold; - private long mMemFullThreshold; /** * This string is used for ServiceManager access to this class. @@ -159,244 +155,107 @@ public class DeviceStorageMonitorService extends SystemService { private static final String TV_NOTIFICATION_CHANNEL_ID = "devicestoragemonitor.tv"; /** - * Handler that checks the amount of disk space on the device and sends a - * notification if the device runs low on disk space - */ - private final Handler mHandler = new Handler() { + * Handler that checks the amount of disk space on the device and sends a + * notification if the device runs low on disk space + */ + private final Handler mHandler = new Handler(IoThread.get().getLooper()) { @Override public void handleMessage(Message msg) { - //don't handle an invalid message switch (msg.what) { - case DEVICE_MEMORY_WHAT: - checkMemory(msg.arg1 == _TRUE); - return; - case FORCE_MEMORY_WHAT: - forceMemory(msg.arg1, msg.arg2); - return; - default: - Slog.w(TAG, "Will not process invalid message"); + case MSG_CHECK: + check(); return; } } }; - private class CachePackageDataObserver extends IPackageDataObserver.Stub { - public void onRemoveCompleted(String packageName, boolean succeeded) { - mClearSucceeded = succeeded; - mClearingCache = false; - if(localLOGV) Slog.i(TAG, " Clear succeeded:"+mClearSucceeded - +", mClearingCache:"+mClearingCache+" Forcing memory check"); - postCheckMemoryMsg(false, 0); - } - } - - private void restatDataDir() { - try { - mDataFileStats.restat(DATA_PATH.getAbsolutePath()); - mFreeMem = (long) mDataFileStats.getAvailableBlocks() * - mDataFileStats.getBlockSize(); - } catch (IllegalArgumentException e) { - // use the old value of mFreeMem - } - // Allow freemem to be overridden by debug.freemem for testing - String debugFreeMem = SystemProperties.get("debug.freemem"); - if (!"".equals(debugFreeMem)) { - mFreeMem = Long.parseLong(debugFreeMem); - } - // Read the log interval from secure settings - long freeMemLogInterval = Settings.Global.getLong(mResolver, - Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL, - DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES)*60*1000; - //log the amount of free memory in event log - long currTime = SystemClock.elapsedRealtime(); - if((mLastReportedFreeMemTime == 0) || - (currTime-mLastReportedFreeMemTime) >= freeMemLogInterval) { - mLastReportedFreeMemTime = currTime; - long mFreeSystem = -1, mFreeCache = -1; - try { - mSystemFileStats.restat(SYSTEM_PATH.getAbsolutePath()); - mFreeSystem = (long) mSystemFileStats.getAvailableBlocks() * - mSystemFileStats.getBlockSize(); - } catch (IllegalArgumentException e) { - // ignore; report -1 - } - try { - mCacheFileStats.restat(CACHE_PATH.getAbsolutePath()); - mFreeCache = (long) mCacheFileStats.getAvailableBlocks() * - mCacheFileStats.getBlockSize(); - } catch (IllegalArgumentException e) { - // ignore; report -1 - } - EventLog.writeEvent(EventLogTags.FREE_STORAGE_LEFT, - mFreeMem, mFreeSystem, mFreeCache); - } - // Read the reporting threshold from secure settings - long threshold = Settings.Global.getLong(mResolver, - Settings.Global.DISK_FREE_CHANGE_REPORTING_THRESHOLD, - DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD); - // If mFree changed significantly log the new value - long delta = mFreeMem - mLastReportedFreeMem; - if (delta > threshold || delta < -threshold) { - mLastReportedFreeMem = mFreeMem; - EventLog.writeEvent(EventLogTags.FREE_STORAGE_CHANGED, mFreeMem); - } - } - - private void clearCache() { - if (mClearCacheObserver == null) { - // Lazy instantiation - mClearCacheObserver = new CachePackageDataObserver(); - } - mClearingCache = true; - try { - if (localLOGV) Slog.i(TAG, "Clearing cache"); - IPackageManager.Stub.asInterface(ServiceManager.getService("package")). - freeStorageAndNotify(null, mMemCacheTrimToThreshold, mClearCacheObserver); - } catch (RemoteException e) { - Slog.w(TAG, "Failed to get handle for PackageManger Exception: "+e); - mClearingCache = false; - mClearSucceeded = false; + private State findOrCreateState(UUID uuid) { + State state = mStates.get(uuid); + if (state == null) { + state = new State(); + mStates.put(uuid, state); } + return state; } - void forceMemory(int opts, int seq) { - if ((opts&OPTION_UPDATES_STOPPED) == 0) { - if (mUpdatesStopped) { - mUpdatesStopped = false; - checkMemory(true); - } - } else { - mUpdatesStopped = true; - final boolean forceLow = (opts&OPTION_STORAGE_LOW) != 0; - if (mLowMemFlag != forceLow || (opts&OPTION_FORCE_UPDATE) != 0) { - mLowMemFlag = forceLow; - if (forceLow) { - sendNotification(seq); - } else { - cancelNotification(seq); + /** + * Core logic that checks the storage state of every mounted private volume. + * Since this can do heavy I/O, callers should invoke indirectly using + * {@link #MSG_CHECK}. + */ + @WorkerThread + private void check() { + final StorageManager storage = getContext().getSystemService(StorageManager.class); + final int seq = mSeq.get(); + + // Check every mounted private volume to see if they're low on space + for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { + final File file = vol.getPath(); + final long fullBytes = storage.getStorageFullBytes(file); + final long lowBytes = storage.getStorageLowBytes(file); + + // Automatically trim cached data when nearing the low threshold; + // when it's within 150% of the threshold, we try trimming usage + // back to 200% of the threshold. + if (file.getUsableSpace() < (lowBytes * 3) / 2) { + final PackageManagerService pms = (PackageManagerService) ServiceManager + .getService("package"); + try { + pms.freeStorage(vol.getFsUuid(), lowBytes * 2, 0); + } catch (IOException e) { + Slog.w(TAG, e); } } - } - } - void checkMemory(boolean checkCache) { - if (mUpdatesStopped) { - return; - } - - //if the thread that was started to clear cache is still running do nothing till its - //finished clearing cache. Ideally this flag could be modified by clearCache - // and should be accessed via a lock but even if it does this test will fail now and - //hopefully the next time this flag will be set to the correct value. - if (mClearingCache) { - if(localLOGV) Slog.i(TAG, "Thread already running just skip"); - //make sure the thread is not hung for too long - long diffTime = System.currentTimeMillis() - mThreadStartTime; - if(diffTime > (10*60*1000)) { - Slog.w(TAG, "Thread that clears cache file seems to run for ever"); - } - } else { - restatDataDir(); - if (localLOGV) Slog.v(TAG, "freeMemory="+mFreeMem); - - //post intent to NotificationManager to display icon if necessary - if (mFreeMem < mMemLowThreshold) { - if (checkCache) { - // We are allowed to clear cache files at this point to - // try to get down below the limit, because this is not - // the initial call after a cache clear has been attempted. - // In this case we will try a cache clear if our free - // space has gone below the cache clear limit. - if (mFreeMem < mMemCacheStartTrimThreshold) { - // We only clear the cache if the free storage has changed - // a significant amount since the last time. - if ((mFreeMemAfterLastCacheClear-mFreeMem) - >= ((mMemLowThreshold-mMemCacheStartTrimThreshold)/4)) { - // See if clearing cache helps - // Note that clearing cache is asynchronous and so we do a - // memory check again once the cache has been cleared. - mThreadStartTime = System.currentTimeMillis(); - mClearSucceeded = false; - clearCache(); - } - } - } else { - // This is a call from after clearing the cache. Note - // the amount of free storage at this point. - mFreeMemAfterLastCacheClear = mFreeMem; - if (!mLowMemFlag) { - // We tried to clear the cache, but that didn't get us - // below the low storage limit. Tell the user. - Slog.i(TAG, "Running low on memory. Sending notification"); - sendNotification(0); - mLowMemFlag = true; - } else { - if (localLOGV) Slog.v(TAG, "Running low on memory " + - "notification already sent. do nothing"); - } - } + // Send relevant broadcasts and show notifications based on any + // recently noticed state transitions. + final UUID uuid = StorageManager.convert(vol.getFsUuid()); + final State state = findOrCreateState(uuid); + final long totalBytes = file.getTotalSpace(); + final long usableBytes = file.getUsableSpace(); + + int oldLevel = state.level; + int newLevel; + if (mForceLevel != State.LEVEL_UNKNOWN) { + // When in testing mode, use unknown old level to force sending + // of any relevant broadcasts. + oldLevel = State.LEVEL_UNKNOWN; + newLevel = mForceLevel; + } else if (usableBytes <= fullBytes) { + newLevel = State.LEVEL_FULL; + } else if (usableBytes <= lowBytes) { + newLevel = State.LEVEL_LOW; + } else if (StorageManager.UUID_DEFAULT.equals(uuid) && !isBootImageOnDisk() + && usableBytes < BOOT_IMAGE_STORAGE_REQUIREMENT) { + newLevel = State.LEVEL_LOW; } else { - mFreeMemAfterLastCacheClear = mFreeMem; - if (mLowMemFlag) { - Slog.i(TAG, "Memory available. Cancelling notification"); - cancelNotification(0); - mLowMemFlag = false; - } + newLevel = State.LEVEL_NORMAL; } - if (!mLowMemFlag && !mIsBootImageOnDisk && mFreeMem < BOOT_IMAGE_STORAGE_REQUIREMENT) { - Slog.i(TAG, "No boot image on disk due to lack of space. Sending notification"); - sendNotification(0); - mLowMemFlag = true; - } - if (mFreeMem < mMemFullThreshold) { - if (!mMemFullFlag) { - sendFullNotification(); - mMemFullFlag = true; - } - } else { - if (mMemFullFlag) { - cancelFullNotification(); - mMemFullFlag = false; - } + + // Log whenever we notice drastic storage changes + if ((Math.abs(state.lastUsableBytes - usableBytes) > DEFAULT_LOG_DELTA_BYTES) + || oldLevel != newLevel) { + EventLogTags.writeStorageState(uuid.toString(), oldLevel, newLevel, + usableBytes, totalBytes); + state.lastUsableBytes = usableBytes; } + + updateNotifications(vol, oldLevel, newLevel); + updateBroadcasts(vol, oldLevel, newLevel, seq); + + state.level = newLevel; } - if(localLOGV) Slog.i(TAG, "Posting Message again"); - //keep posting messages to itself periodically - postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL); - } - void postCheckMemoryMsg(boolean clearCache, long delay) { - // Remove queued messages - mHandler.removeMessages(DEVICE_MEMORY_WHAT); - mHandler.sendMessageDelayed(mHandler.obtainMessage(DEVICE_MEMORY_WHAT, - clearCache ?_TRUE : _FALSE, 0), - delay); + // Loop around to check again in future; we don't remove messages since + // there might be an immediate request pending. + if (!mHandler.hasMessages(MSG_CHECK)) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK), + DEFAULT_CHECK_INTERVAL); + } } public DeviceStorageMonitorService(Context context) { super(context); - mLastReportedFreeMemTime = 0; - mResolver = context.getContentResolver(); - mIsBootImageOnDisk = isBootImageOnDisk(); - //create StatFs object - mDataFileStats = new StatFs(DATA_PATH.getAbsolutePath()); - mSystemFileStats = new StatFs(SYSTEM_PATH.getAbsolutePath()); - mCacheFileStats = new StatFs(CACHE_PATH.getAbsolutePath()); - //initialize total storage on device - mTotalMemory = (long)mDataFileStats.getBlockCount() * - mDataFileStats.getBlockSize(); - mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW); - mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND - | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); - mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK); - mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND - | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); - mStorageFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL); - mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL); - mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); } private static boolean isBootImageOnDisk() { @@ -408,35 +267,20 @@ public class DeviceStorageMonitorService extends SystemService { return true; } - /** - * Initializes the disk space threshold value and posts an empty message to - * kickstart the process. - */ @Override public void onStart() { - // cache storage thresholds - Context context = getContext(); - final StorageManager sm = StorageManager.from(context); - mMemLowThreshold = sm.getStorageLowBytes(DATA_PATH); - mMemFullThreshold = sm.getStorageFullBytes(DATA_PATH); - - mMemCacheStartTrimThreshold = ((mMemLowThreshold*3)+mMemFullThreshold)/4; - mMemCacheTrimToThreshold = mMemLowThreshold - + ((mMemLowThreshold-mMemCacheStartTrimThreshold)*2); - mFreeMemAfterLastCacheClear = mTotalMemory; - checkMemory(true); + final Context context = getContext(); + mNotifManager = context.getSystemService(NotificationManager.class); mCacheFileDeletedObserver = new CacheFileDeletedObserver(); mCacheFileDeletedObserver.startWatching(); // Ensure that the notification channel is set up - NotificationManager notificationMgr = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); PackageManager packageManager = context.getPackageManager(); boolean isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK); if (isTv) { - notificationMgr.createNotificationChannel(new NotificationChannel( + mNotifManager.createNotificationChannel(new NotificationChannel( TV_NOTIFICATION_CHANNEL_ID, context.getString( com.android.internal.R.string.device_storage_monitor_notification_channel), @@ -445,23 +289,29 @@ public class DeviceStorageMonitorService extends SystemService { publishBinderService(SERVICE, mRemoteService); publishLocalService(DeviceStorageMonitorInternal.class, mLocalService); + + // Kick off pass to examine storage state + mHandler.removeMessages(MSG_CHECK); + mHandler.obtainMessage(MSG_CHECK).sendToTarget(); } private final DeviceStorageMonitorInternal mLocalService = new DeviceStorageMonitorInternal() { @Override public void checkMemory() { - // force an early check - postCheckMemoryMsg(true, 0); + // Kick off pass to examine storage state + mHandler.removeMessages(MSG_CHECK); + mHandler.obtainMessage(MSG_CHECK).sendToTarget(); } @Override public boolean isMemoryLow() { - return mLowMemFlag; + return Environment.getDataDirectory().getUsableSpace() < getMemoryLowThreshold(); } @Override public long getMemoryLowThreshold() { - return mMemLowThreshold; + return getContext().getSystemService(StorageManager.class) + .getStorageLowBytes(Environment.getDataDirectory()); } }; @@ -494,8 +344,6 @@ public class DeviceStorageMonitorService extends SystemService { } static final int OPTION_FORCE_UPDATE = 1<<0; - static final int OPTION_UPDATES_STOPPED = 1<<1; - static final int OPTION_STORAGE_LOW = 1<<2; int parseOptions(Shell shell) { String opt; @@ -518,10 +366,11 @@ public class DeviceStorageMonitorService extends SystemService { int opts = parseOptions(shell); getContext().enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null); + mForceLevel = State.LEVEL_LOW; int seq = mSeq.incrementAndGet(); - mHandler.sendMessage(mHandler.obtainMessage(FORCE_MEMORY_WHAT, - opts | OPTION_UPDATES_STOPPED | OPTION_STORAGE_LOW, seq)); if ((opts & OPTION_FORCE_UPDATE) != 0) { + mHandler.removeMessages(MSG_CHECK); + mHandler.obtainMessage(MSG_CHECK).sendToTarget(); pw.println(seq); } } break; @@ -529,10 +378,11 @@ public class DeviceStorageMonitorService extends SystemService { int opts = parseOptions(shell); getContext().enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null); + mForceLevel = State.LEVEL_NORMAL; int seq = mSeq.incrementAndGet(); - mHandler.sendMessage(mHandler.obtainMessage(FORCE_MEMORY_WHAT, - opts | OPTION_UPDATES_STOPPED, seq)); if ((opts & OPTION_FORCE_UPDATE) != 0) { + mHandler.removeMessages(MSG_CHECK); + mHandler.obtainMessage(MSG_CHECK).sendToTarget(); pw.println(seq); } } break; @@ -540,10 +390,11 @@ public class DeviceStorageMonitorService extends SystemService { int opts = parseOptions(shell); getContext().enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null); + mForceLevel = State.LEVEL_UNKNOWN; int seq = mSeq.incrementAndGet(); - mHandler.sendMessage(mHandler.obtainMessage(FORCE_MEMORY_WHAT, - opts, seq)); if ((opts & OPTION_FORCE_UPDATE) != 0) { + mHandler.removeMessages(MSG_CHECK); + mHandler.obtainMessage(MSG_CHECK).sendToTarget(); pw.println(seq); } } break; @@ -568,145 +419,125 @@ public class DeviceStorageMonitorService extends SystemService { pw.println(" -f: force a storage change broadcast be sent, prints new sequence."); } - void dumpImpl(FileDescriptor fd, PrintWriter pw, String[] args) { + void dumpImpl(FileDescriptor fd, PrintWriter _pw, String[] args) { + final IndentingPrintWriter pw = new IndentingPrintWriter(_pw, " "); if (args == null || args.length == 0 || "-a".equals(args[0])) { - final Context context = getContext(); - - pw.println("Current DeviceStorageMonitor state:"); - - pw.print(" mFreeMem="); - pw.print(Formatter.formatFileSize(context, mFreeMem)); - pw.print(" mTotalMemory="); - pw.println(Formatter.formatFileSize(context, mTotalMemory)); - - pw.print(" mFreeMemAfterLastCacheClear="); - pw.println(Formatter.formatFileSize(context, mFreeMemAfterLastCacheClear)); - - pw.print(" mLastReportedFreeMem="); - pw.print(Formatter.formatFileSize(context, mLastReportedFreeMem)); - pw.print(" mLastReportedFreeMemTime="); - TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw); - pw.println(); - - if (mUpdatesStopped) { - pw.print(" mUpdatesStopped="); - pw.print(mUpdatesStopped); - pw.print(" mSeq="); - pw.println(mSeq.get()); - } else { - pw.print(" mClearSucceeded="); - pw.print(mClearSucceeded); - pw.print(" mClearingCache="); - pw.println(mClearingCache); + pw.println("Known volumes:"); + pw.increaseIndent(); + for (int i = 0; i < mStates.size(); i++) { + final UUID uuid = mStates.keyAt(i); + final State state = mStates.valueAt(i); + if (StorageManager.UUID_DEFAULT.equals(uuid)) { + pw.println("Default:"); + } else { + pw.println(uuid + ":"); + } + pw.increaseIndent(); + pw.printPair("level", State.levelToString(state.level)); + pw.printPair("lastUsableBytes", state.lastUsableBytes); + pw.println(); + pw.decreaseIndent(); } + pw.decreaseIndent(); + pw.println(); - pw.print(" mLowMemFlag="); - pw.print(mLowMemFlag); - pw.print(" mMemFullFlag="); - pw.println(mMemFullFlag); - - pw.print(" mMemLowThreshold="); - pw.print(Formatter.formatFileSize(context, mMemLowThreshold)); - pw.print(" mMemFullThreshold="); - pw.println(Formatter.formatFileSize(context, mMemFullThreshold)); - - pw.print(" mMemCacheStartTrimThreshold="); - pw.print(Formatter.formatFileSize(context, mMemCacheStartTrimThreshold)); - pw.print(" mMemCacheTrimToThreshold="); - pw.println(Formatter.formatFileSize(context, mMemCacheTrimToThreshold)); + pw.printPair("mSeq", mSeq.get()); + pw.printPair("mForceState", State.levelToString(mForceLevel)); + pw.println(); + pw.println(); - pw.print(" mIsBootImageOnDisk="); pw.println(mIsBootImageOnDisk); } else { Shell shell = new Shell(); shell.exec(mRemoteService, null, fd, null, args, null, new ResultReceiver(null)); } } - /** - * This method sends a notification to NotificationManager to display - * an error dialog indicating low disk space and launch the Installer - * application - */ - private void sendNotification(int seq) { + private void updateNotifications(VolumeInfo vol, int oldLevel, int newLevel) { final Context context = getContext(); - if(localLOGV) Slog.i(TAG, "Sending low memory notification"); - //log the event to event log with the amount of free storage(in bytes) left on the device - EventLog.writeEvent(EventLogTags.LOW_STORAGE, mFreeMem); - // Pack up the values and broadcast them to everyone - Intent lowMemIntent = new Intent(StorageManager.ACTION_MANAGE_STORAGE); - lowMemIntent.putExtra("memory", mFreeMem); - lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - NotificationManager notificationMgr = - (NotificationManager)context.getSystemService( - Context.NOTIFICATION_SERVICE); - CharSequence title = context.getText( - com.android.internal.R.string.low_internal_storage_view_title); - CharSequence details = context.getText(mIsBootImageOnDisk - ? com.android.internal.R.string.low_internal_storage_view_text - : com.android.internal.R.string.low_internal_storage_view_text_no_boot); - PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent, 0, - null, UserHandle.CURRENT); - Notification notification = - new Notification.Builder(context, SystemNotificationChannels.ALERTS) - .setSmallIcon(com.android.internal.R.drawable.stat_notify_disk_full) - .setTicker(title) - .setColor(context.getColor( - com.android.internal.R.color.system_notification_accent_color)) - .setContentTitle(title) - .setContentText(details) - .setContentIntent(intent) - .setStyle(new Notification.BigTextStyle() - .bigText(details)) - .setVisibility(Notification.VISIBILITY_PUBLIC) - .setCategory(Notification.CATEGORY_SYSTEM) - .extend(new Notification.TvExtender() - .setChannelId(TV_NOTIFICATION_CHANNEL_ID)) - .build(); - notification.flags |= Notification.FLAG_NO_CLEAR; - notificationMgr.notifyAsUser(null, SystemMessage.NOTE_LOW_STORAGE, notification, - UserHandle.ALL); - Intent broadcast = new Intent(mStorageLowIntent); - if (seq != 0) { - broadcast.putExtra(EXTRA_SEQUENCE, seq); + final UUID uuid = StorageManager.convert(vol.getFsUuid()); + + if (State.isEntering(State.LEVEL_LOW, oldLevel, newLevel)) { + Intent lowMemIntent = new Intent(StorageManager.ACTION_MANAGE_STORAGE); + lowMemIntent.putExtra(StorageManager.EXTRA_UUID, uuid); + lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + final CharSequence title = context.getText( + com.android.internal.R.string.low_internal_storage_view_title); + + final CharSequence details; + if (StorageManager.UUID_DEFAULT.equals(uuid)) { + details = context.getText(isBootImageOnDisk() + ? com.android.internal.R.string.low_internal_storage_view_text + : com.android.internal.R.string.low_internal_storage_view_text_no_boot); + } else { + details = context.getText( + com.android.internal.R.string.low_internal_storage_view_text); + } + + PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent, 0, + null, UserHandle.CURRENT); + Notification notification = + new Notification.Builder(context, SystemNotificationChannels.ALERTS) + .setSmallIcon(com.android.internal.R.drawable.stat_notify_disk_full) + .setTicker(title) + .setColor(context.getColor( + com.android.internal.R.color.system_notification_accent_color)) + .setContentTitle(title) + .setContentText(details) + .setContentIntent(intent) + .setStyle(new Notification.BigTextStyle() + .bigText(details)) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setCategory(Notification.CATEGORY_SYSTEM) + .extend(new Notification.TvExtender() + .setChannelId(TV_NOTIFICATION_CHANNEL_ID)) + .build(); + notification.flags |= Notification.FLAG_NO_CLEAR; + mNotifManager.notifyAsUser(uuid.toString(), SystemMessage.NOTE_LOW_STORAGE, + notification, UserHandle.ALL); + } else if (State.isLeaving(State.LEVEL_LOW, oldLevel, newLevel)) { + mNotifManager.cancelAsUser(uuid.toString(), SystemMessage.NOTE_LOW_STORAGE, + UserHandle.ALL); } - context.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); } - /** - * Cancels low storage notification and sends OK intent. - */ - private void cancelNotification(int seq) { - final Context context = getContext(); - if(localLOGV) Slog.i(TAG, "Canceling low memory notification"); - NotificationManager mNotificationMgr = - (NotificationManager)context.getSystemService( - Context.NOTIFICATION_SERVICE); - //cancel notification since memory has been freed - mNotificationMgr.cancelAsUser(null, SystemMessage.NOTE_LOW_STORAGE, UserHandle.ALL); - - context.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL); - Intent broadcast = new Intent(mStorageOkIntent); - if (seq != 0) { - broadcast.putExtra(EXTRA_SEQUENCE, seq); + private void updateBroadcasts(VolumeInfo vol, int oldLevel, int newLevel, int seq) { + if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, vol.getFsUuid())) { + // We don't currently send broadcasts for secondary volumes + return; } - context.sendBroadcastAsUser(broadcast, UserHandle.ALL); - } - /** - * Send a notification when storage is full. - */ - private void sendFullNotification() { - if(localLOGV) Slog.i(TAG, "Sending memory full notification"); - getContext().sendStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL); - } + final Intent lowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND + | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) + .putExtra(EXTRA_SEQUENCE, seq); + final Intent notLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND + | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) + .putExtra(EXTRA_SEQUENCE, seq); + + if (State.isEntering(State.LEVEL_LOW, oldLevel, newLevel)) { + getContext().sendStickyBroadcastAsUser(lowIntent, UserHandle.ALL); + } else if (State.isLeaving(State.LEVEL_LOW, oldLevel, newLevel)) { + getContext().removeStickyBroadcastAsUser(lowIntent, UserHandle.ALL); + getContext().sendBroadcastAsUser(notLowIntent, UserHandle.ALL); + } - /** - * Cancels memory full notification and sends "not full" intent. - */ - private void cancelFullNotification() { - if(localLOGV) Slog.i(TAG, "Canceling memory full notification"); - getContext().removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL); - getContext().sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL); + final Intent fullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) + .putExtra(EXTRA_SEQUENCE, seq); + final Intent notFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) + .putExtra(EXTRA_SEQUENCE, seq); + + if (State.isEntering(State.LEVEL_FULL, oldLevel, newLevel)) { + getContext().sendStickyBroadcastAsUser(fullIntent, UserHandle.ALL); + } else if (State.isLeaving(State.LEVEL_FULL, oldLevel, newLevel)) { + getContext().removeStickyBroadcastAsUser(fullIntent, UserHandle.ALL); + getContext().sendBroadcastAsUser(notFullIntent, UserHandle.ALL); + } } private static class CacheFileDeletedObserver extends FileObserver { diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index 4044fdb07b0d..b937f9d4c6d8 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -96,6 +96,7 @@ import java.util.Objects; public class VrManagerService extends SystemService implements EnabledComponentChangeListener{ public static final String TAG = "VrManagerService"; + static final boolean DBG = false; private static final int PENDING_STATE_DELAY_MS = 300; private static final int EVENT_LOG_SIZE = 32; @@ -157,7 +158,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC private void setVrModeAllowedLocked(boolean allowed) { if (mVrModeAllowed != allowed) { mVrModeAllowed = allowed; - Slog.i(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed")); + if (DBG) Slog.d(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed")); if (mVrModeAllowed) { consumeAndApplyPendingStateLocked(); } else { diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index a38addb1dad0..9d8f1241a7ae 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -52,6 +52,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.GraphicBuffer; import android.graphics.Path; import android.graphics.Rect; import android.os.Binder; @@ -346,12 +347,12 @@ public class AppTransition implements Dump { mAppTransitionState = APP_STATE_TIMEOUT; } - Bitmap getAppTransitionThumbnailHeader(int taskId) { + GraphicBuffer getAppTransitionThumbnailHeader(int taskId) { AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId); if (spec == null) { spec = mDefaultNextAppTransitionAnimationSpec; } - return spec != null ? spec.bitmap : null; + return spec != null ? spec.buffer : null; } /** Returns whether the next thumbnail transition is aspect scaled up. */ @@ -716,9 +717,9 @@ public class AppTransition implements Dump { } private void putDefaultNextAppTransitionCoordinates(int left, int top, int width, int height, - Bitmap bitmap) { + GraphicBuffer buffer) { mDefaultNextAppTransitionAnimationSpec = new AppTransitionAnimationSpec(-1 /* taskId */, - bitmap, new Rect(left, top, left + width, top + height)); + buffer, new Rect(left, top, left + width, top + height)); } /** @@ -943,7 +944,7 @@ public class AppTransition implements Dump { * when a thumbnail is specified with the pending animation override. */ Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, @Nullable Rect contentInsets, - Bitmap thumbnailHeader, final int taskId, int uiMode, int orientation) { + GraphicBuffer thumbnailHeader, final int taskId, int uiMode, int orientation) { Animation a; final int thumbWidthI = thumbnailHeader.getWidth(); final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; @@ -1296,7 +1297,7 @@ public class AppTransition implements Dump { * when a thumbnail is specified with the pending animation override. */ Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit, - Bitmap thumbnailHeader) { + GraphicBuffer thumbnailHeader) { Animation a; getDefaultNextAppTransitionStartRect(mTmpRect); final int thumbWidthI = thumbnailHeader.getWidth(); @@ -1341,7 +1342,7 @@ public class AppTransition implements Dump { int transit, int taskId) { final int appWidth = containingFrame.width(); final int appHeight = containingFrame.height(); - Bitmap thumbnailHeader = getAppTransitionThumbnailHeader(taskId); + final GraphicBuffer thumbnailHeader = getAppTransitionThumbnailHeader(taskId); Animation a; getDefaultNextAppTransitionStartRect(mTmpRect); final int thumbWidthI = thumbnailHeader != null ? thumbnailHeader.getWidth() : appWidth; @@ -1714,7 +1715,7 @@ public class AppTransition implements Dump { } } - void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, + void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp) { if (isTransitionSet()) { clear(); @@ -1729,7 +1730,7 @@ public class AppTransition implements Dump { } } - void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY, + void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) { if (isTransitionSet()) { clear(); @@ -1763,7 +1764,7 @@ public class AppTransition implements Dump { // to be set. Rect rect = spec.rect; putDefaultNextAppTransitionCoordinates(rect.left, rect.top, - rect.width(), rect.height(), spec.bitmap); + rect.width(), rect.height(), spec.buffer); } } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 221e7957ef35..b5476d7e056b 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3492,10 +3492,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (win != null) { final int req = win.mAttrs.screenOrientation; - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req); if (policy.isKeyguardHostWindow(win.mAttrs)) { mLastKeyguardForcedOrientation = req; + if (mService.mKeyguardGoingAway) { + // Keyguard can't affect the orientation if it is going away... + mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; + return SCREEN_ORIENTATION_UNSET; + } } + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req); return (mLastWindowForcedOrientation = req); } diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index fc4ec2889523..9a9e29a7eb88 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -92,17 +92,16 @@ class PinnedStackController { private final Rect mStableInsets = new Rect(); // The size and position information that describes where the pinned stack will go by default. + private int mDefaultMinSize; private int mDefaultStackGravity; private float mDefaultAspectRatio; private Point mScreenEdgeInsets; + private int mCurrentMinSize; // The aspect ratio bounds of the PIP. private float mMinAspectRatio; private float mMaxAspectRatio; - // The minimum edge size of the normal PiP bounds. - private int mMinSize; - // Temp vars for calculation private final DisplayMetrics mTmpMetrics = new DisplayMetrics(); private final Rect mTmpInsets = new Rect(); @@ -124,6 +123,13 @@ class PinnedStackController { } @Override + public void setMinEdgeSize(int minEdgeSize) { + mHandler.post(() -> { + mCurrentMinSize = Math.max(mDefaultMinSize, minEdgeSize); + }); + } + + @Override public int getDisplayRotation() { synchronized (mService.mWindowMap) { return mDisplayInfo.rotation; @@ -160,10 +166,12 @@ class PinnedStackController { */ private void reloadResources() { final Resources res = mService.mContext.getResources(); - mMinSize = res.getDimensionPixelSize( + mDefaultMinSize = res.getDimensionPixelSize( com.android.internal.R.dimen.default_minimal_size_pip_resizable_task); + mCurrentMinSize = mDefaultMinSize; mDefaultAspectRatio = res.getFloat( com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio); + mAspectRatio = mDefaultAspectRatio; final String screenEdgeInsetsDpString = res.getString( com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets); final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty() @@ -212,11 +220,15 @@ class PinnedStackController { * Returns the current bounds (or the default bounds if there are no current bounds) with the * specified aspect ratio. */ - Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio) { + Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio, + boolean useCurrentMinEdgeSize) { // Save the snap fraction, calculate the aspect ratio based on screen size final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds)); - final Size size = getSize(aspectRatio); + + final int minEdgeSize = useCurrentMinEdgeSize ? mCurrentMinSize : mDefaultMinSize; + final Size size = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, minEdgeSize, + mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f); final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f); stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight()); @@ -228,16 +240,6 @@ class PinnedStackController { } /** - * @return the size of the PIP based on the given {@param aspectRatio}. - */ - Size getSize(float aspectRatio) { - synchronized (mService.mWindowMap) { - return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize, - mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); - } - } - - /** * @return the default bounds to show the PIP when there is no active PIP. */ Rect getDefaultBounds() { @@ -246,7 +248,8 @@ class PinnedStackController { getInsetBounds(insetBounds); final Rect defaultBounds = new Rect(); - final Size size = getSize(mDefaultAspectRatio); + final Size size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio, + mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds, 0, mIsImeShowing ? mImeHeight : 0, defaultBounds); return defaultBounds; @@ -401,7 +404,8 @@ class PinnedStackController { getInsetBounds(insetBounds); final Rect normalBounds = getDefaultBounds(); if (isValidPictureInPictureAspectRatio(mAspectRatio)) { - transformBoundsToAspectRatio(normalBounds, mAspectRatio); + transformBoundsToAspectRatio(normalBounds, mAspectRatio, + false /* useCurrentMinEdgeSize */); } final Rect animatingBounds = mTmpAnimatingBoundsRect; final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID); diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java index 0c628acba92c..989e8f23693a 100644 --- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java +++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java @@ -17,7 +17,6 @@ package com.android.server.wm; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; -import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS; import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END; @@ -36,7 +35,8 @@ import java.util.List; */ public class PinnedStackWindowController extends StackWindowController { - private Rect mTmpBoundsRect = new Rect(); + private Rect mTmpFromBounds = new Rect(); + private Rect mTmpToBounds = new Rect(); public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener, int displayId, boolean onTop, Rect outBounds) { @@ -44,16 +44,16 @@ public class PinnedStackWindowController extends StackWindowController { } /** - * @param useExistingStackBounds Apply {@param aspectRatio} to the existing target stack bounds - * if possible + * @return the {@param currentStackBounds} transformed to the give {@param aspectRatio}. If + * {@param currentStackBounds} is null, then the {@param aspectRatio} is applied to the + * default bounds. */ - public Rect getPictureInPictureBounds(float aspectRatio, boolean useExistingStackBounds) { + public Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) { synchronized (mWindowMap) { if (!mService.mSupportsPictureInPicture || mContainer == null) { return null; } - final Rect stackBounds; final DisplayContent displayContent = mContainer.getDisplayContent(); if (displayContent == null) { return null; @@ -61,18 +61,14 @@ public class PinnedStackWindowController extends StackWindowController { final PinnedStackController pinnedStackController = displayContent.getPinnedStackController(); - if (useExistingStackBounds) { - // If the stack exists, then use its final bounds to calculate the new aspect ratio - // bounds - stackBounds = new Rect(); - mContainer.getAnimationOrCurrentBounds(stackBounds); - } else { - // Otherwise, just calculate the aspect ratio bounds from the default bounds + if (stackBounds == null) { + // Calculate the aspect ratio bounds from the default bounds stackBounds = pinnedStackController.getDefaultBounds(); } if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) { - return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio); + return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio, + true /* useCurrentMinEdgeSize */); } else { return stackBounds; } @@ -104,10 +100,10 @@ public class PinnedStackWindowController extends StackWindowController { } schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START; - mService.getStackBounds(FULLSCREEN_WORKSPACE_STACK_ID, mTmpBoundsRect); - if (!mTmpBoundsRect.isEmpty()) { + mService.getStackBounds(FULLSCREEN_WORKSPACE_STACK_ID, mTmpToBounds); + if (!mTmpToBounds.isEmpty()) { // If there is a fullscreen bounds, use that - toBounds = new Rect(mTmpBoundsRect); + toBounds = new Rect(mTmpToBounds); } else { // Otherwise, use the display bounds toBounds = new Rect(); @@ -142,16 +138,15 @@ public class PinnedStackWindowController extends StackWindowController { return; } - final Rect toBounds = getPictureInPictureBounds(aspectRatio, - true /* useExistingStackBounds */); - final Rect targetBounds = new Rect(); - mContainer.getAnimationOrCurrentBounds(targetBounds); final PinnedStackController pinnedStackController = mContainer.getDisplayContent().getPinnedStackController(); if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) != 0) { - if (!toBounds.equals(targetBounds)) { - animateResizePinnedStack(toBounds, null /* sourceHintBounds */, + mContainer.getAnimationOrCurrentBounds(mTmpFromBounds); + mTmpToBounds.set(mTmpFromBounds); + getPictureInPictureBounds(aspectRatio, mTmpToBounds); + if (!mTmpToBounds.equals(mTmpFromBounds)) { + animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */, -1 /* duration */, false /* fromFullscreen */); } pinnedStackController.setAspectRatio( diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 233e75bbfec7..fb500bc256fd 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -858,14 +858,20 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { final int privateflags = attrs.privateFlags; boolean displayHasContent = false; + if (DEBUG_KEEP_SCREEN_ON && (attrFlags & FLAG_KEEP_SCREEN_ON) != 0 + && w != mService.mLastWakeLockHoldingWindow) { + Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + + " has FLAG_KEEP_SCREEN_ON set, hasSurface=" + w.mHasSurface + + ", canBeSeen=" + canBeSeen); + } + if (w.mHasSurface && canBeSeen) { if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) { mHoldScreen = w.mSession; mHoldScreenWindow = w; } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) { Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding " - + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by" - + Debug.getCallers(10)); + + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!!"); } if (!syswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) { mScreenBrightness = w.mAttrs.screenBrightness; diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index b2667781b955..1f7ef5014d36 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -31,6 +31,9 @@ import android.graphics.Rect; import android.os.Environment; import android.os.Handler; import android.util.ArraySet; +import android.view.DisplayListCanvas; +import android.view.RenderNode; +import android.view.ThreadedRenderer; import android.view.WindowManager.LayoutParams; import android.view.WindowManagerPolicy.ScreenOffListener; import android.view.WindowManagerPolicy.StartingSurface; @@ -238,19 +241,22 @@ class TaskSnapshotController { final int color = task.getTaskDescription().getBackgroundColor(); final int statusBarColor = task.getTaskDescription().getStatusBarColor(); final int navigationBarColor = task.getTaskDescription().getNavigationBarColor(); - final Bitmap b = Bitmap.createBitmap(mainWindow.getFrameLw().width(), - mainWindow.getFrameLw().height(), ARGB_8888); - final Canvas c = new Canvas(b); - c.drawColor(color); final LayoutParams attrs = mainWindow.getAttrs(); final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags, attrs.privateFlags, attrs.systemUiVisibility, statusBarColor, navigationBarColor); + final int width = mainWindow.getFrameLw().width(); + final int height = mainWindow.getFrameLw().height(); + + final RenderNode node = RenderNode.create("TaskSnapshotController", null); + node.setLeftTopRightBottom(0, 0, width, height); + node.setClipToBounds(false); + final DisplayListCanvas c = node.start(width, height); + c.drawColor(color); decorPainter.setInsets(mainWindow.mContentInsets, mainWindow.mStableInsets); decorPainter.drawDecors(c, null /* statusBarExcludeFrame */); + node.end(c); + final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height); - // Flush writer. - c.setBitmap(null); - final Bitmap hwBitmap = b.copy(HARDWARE, false /* isMutable */); return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(), topChild.getConfiguration().orientation, mainWindow.mStableInsets, false /* reduced */, 1.0f /* scale */); diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java index 8279b5167766..c080f344c186 100644 --- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java +++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java @@ -77,5 +77,5 @@ public class WindowManagerDebugConfig { static final boolean DEBUG_UNKNOWN_APP_VISIBILITY = false; static final String TAG_KEEP_SCREEN_ON = "DebugKeepScreenOn"; - static final boolean DEBUG_KEEP_SCREEN_ON = false; + static final boolean DEBUG_KEEP_SCREEN_ON = true; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index a15891bc6414..02fdfeeb365d 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -123,6 +123,7 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.ContentObserver; import android.graphics.Bitmap; +import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Point; @@ -349,6 +350,7 @@ public class WindowManagerService extends IWindowManager.Stub private static final int ANIMATION_DURATION_SCALE = 2; final private KeyguardDisableHandler mKeyguardDisableHandler; + boolean mKeyguardGoingAway; private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -2629,7 +2631,7 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, + public void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp) { synchronized(mWindowMap) { mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY, @@ -2638,7 +2640,7 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, + public void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) { synchronized(mWindowMap) { @@ -2876,6 +2878,12 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void setKeyguardGoingAway(boolean keyguardGoingAway) { + synchronized (mWindowMap) { + mKeyguardGoingAway = keyguardGoingAway; + } + } + // ------------------------------------------------------------- // Misc IWindowSession methods // ------------------------------------------------------------- @@ -3816,20 +3824,22 @@ public class WindowManagerService extends IWindowManager.Stub long origId = Binder.clearCallingIdentity(); try { - final boolean rotationChanged; // TODO(multi-display): Update rotation for different displays separately. - final DisplayContent displayContent = getDefaultDisplayContentLocked(); + final boolean rotationChanged; + final int displayId; synchronized (mWindowMap) { + final DisplayContent displayContent = getDefaultDisplayContentLocked(); rotationChanged = displayContent.updateRotationUnchecked( false /* inTransaction */); if (!rotationChanged || forceRelayout) { - getDefaultDisplayContentLocked().setLayoutNeeded(); + displayContent.setLayoutNeeded(); mWindowPlacerLocked.performSurfacePlacement(); } + displayId = displayContent.getDisplayId(); } if (rotationChanged || alwaysSendConfiguration) { - sendNewConfiguration(displayContent.getDisplayId()); + sendNewConfiguration(displayId); } } finally { Binder.restoreCallingIdentity(origId); @@ -6457,7 +6467,7 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" window="); pw.print(mWindowAnimationScaleSetting); pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); - pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation); + pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation); pw.println(" mLayoutToAnim:"); mAppTransition.dump(pw, " "); } @@ -6890,9 +6900,11 @@ public class WindowManagerService extends IWindowManager.Stub "registerDockedStackListener()")) { return; } - // TODO(multi-display): The listener is registered on the default display only. - getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener( - listener); + synchronized (mWindowMap) { + // TODO(multi-display): The listener is registered on the default display only. + getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener( + listener); + } } @Override @@ -7173,6 +7185,11 @@ public class WindowManagerService extends IWindowManager.Stub } @Override + public boolean isKeyguardGoingAway() { + return WindowManagerService.this.mKeyguardGoingAway; + } + + @Override public void showGlobalActions() { WindowManagerService.this.showGlobalActions(); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index acd7703836d1..44a867c9b65f 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2202,18 +2202,30 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - void prepareWindowToDisplayDuringRelayout(MergedConfiguration mergedConfiguration) { + void prepareWindowToDisplayDuringRelayout(MergedConfiguration mergedConfiguration, + boolean wasVisible) { + // We need to turn on screen regardless of visibility. + if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) { + if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this); + mTurnOnScreen = true; + } + + // If we were already visible, skip rest of preparation. + if (wasVisible) { + if (DEBUG_VISIBILITY) Slog.v(TAG, + "Already visible and does not turn on screen, skip preparing: " + this); + return; + } + if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST) == SOFT_INPUT_ADJUST_RESIZE) { mLayoutNeeded = true; } + if (isDrawnLw() && mService.okToDisplay()) { mWinAnimator.applyEnterAnimationLocked(); } - if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) { - if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this); - mTurnOnScreen = true; - } + if (isConfigChanged()) { final Configuration globalConfig = mService.mRoot.getConfiguration(); final Configuration overrideConfig = getMergedOverrideConfiguration(); @@ -3407,7 +3419,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.print(prefix); pw.print("mOrientationChanging="); pw.print(mOrientationChanging); pw.print(" mAppFreezing="); pw.print(mAppFreezing); - pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen); + pw.print(" mTurnOnScreen="); pw.print(mTurnOnScreen); pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged); } if (mLastFreezeDuration != 0) { @@ -4348,9 +4360,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mLastVisibleLayoutRotation = getDisplayContent().getRotation(); mWinAnimator.mEnteringAnimation = true; - if (!wasVisible) { - prepareWindowToDisplayDuringRelayout(mergedConfiguration); - } + + prepareWindowToDisplayDuringRelayout(mergedConfiguration, wasVisible); + if ((attrChanges & FORMAT_CHANGED) != 0) { // If the format can't be changed in place, preserve the old surface until the app draws // on the new one. This prevents blinking when we change elevation of freeform and diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index d75afcf357a8..73f8d27bc7a6 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -687,6 +687,7 @@ class WindowStateAnimator { mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, attrs.getTitle().toString(), width, height, format, flags, this, windowType, ownerUid); + mSurfaceFormat = format; w.setHasSurface(true); diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 4a1a7052a8b0..cb1b2e6abc58 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -38,11 +38,9 @@ import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; import android.content.res.Configuration; -import android.graphics.Bitmap; -import android.graphics.Canvas; +import android.graphics.GraphicBuffer; import android.graphics.PixelFormat; import android.graphics.Rect; -import android.os.Binder; import android.os.Debug; import android.os.Trace; import android.util.ArraySet; @@ -675,8 +673,9 @@ class WindowSurfacePlacer { return; } final int taskId = appToken.getTask().mTaskId; - Bitmap thumbnailHeader = mService.mAppTransition.getAppTransitionThumbnailHeader(taskId); - if (thumbnailHeader == null || thumbnailHeader.getConfig() == Bitmap.Config.ALPHA_8) { + final GraphicBuffer thumbnailHeader = + mService.mAppTransition.getAppTransitionThumbnailHeader(taskId); + if (thumbnailHeader == null) { if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId); return; } @@ -700,12 +699,10 @@ class WindowSurfacePlacer { Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE"); } - // Draw the thumbnail onto the surface + // Transfer the thumbnail to the surface Surface drawSurface = new Surface(); drawSurface.copyFrom(surfaceControl); - Canvas c = drawSurface.lockCanvas(dirty); - c.drawBitmap(thumbnailHeader, 0, 0, null); - drawSurface.unlockCanvasAndPost(c); + drawSurface.attachAndQueueBuffer(thumbnailHeader); drawSurface.release(); // Get the thumbnail animation diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index 9cfa542da9d1..bac121695ed9 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -235,8 +235,7 @@ public class ActivityTestsBase { if (mStackId == ActivityManager.StackId.PINNED_STACK_ID) { mStack = new PinnedActivityStack(this, recents, mOnTop) { @Override - Rect getPictureInPictureBounds(float aspectRatio, - boolean useExistingStackBounds) { + Rect getDefaultPictureInPictureBounds(float aspectRatio) { return new Rect(50, 50, 100, 100); } }; diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java index 5f5189825deb..c809c325726f 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import android.util.MergedConfiguration; +import android.view.WindowManager; import org.junit.Test; import org.junit.runner.RunWith; @@ -204,4 +206,20 @@ public class WindowStateTests extends WindowTestsBase { assertEquals(mediaChild, windows.pollFirst()); assertTrue(windows.isEmpty()); } + + @Test + public void testPrepareWindowToDisplayDuringRelayout() throws Exception { + testPrepareWindowToDisplayDuringRelayout(false /*wasVisible*/); + testPrepareWindowToDisplayDuringRelayout(true /*wasVisible*/); + } + + private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) { + final WindowState root = createWindow(null, TYPE_APPLICATION, "root"); + root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; + root.mTurnOnScreen = false; + + root.prepareWindowToDisplayDuringRelayout(new MergedConfiguration(), + wasVisible /*wasVisible*/); + assertTrue(root.mTurnOnScreen); + } } diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java index 16b73d5515e5..562443f53546 100644 --- a/services/usage/java/com/android/server/usage/StorageStatsService.java +++ b/services/usage/java/com/android/server/usage/StorageStatsService.java @@ -62,6 +62,8 @@ import com.android.server.pm.Installer; import com.android.server.pm.Installer.InstallerException; import com.android.server.storage.CacheQuotaStrategy; +import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; public class StorageStatsService extends IStorageStatsManager.Stub { @@ -181,29 +183,42 @@ public class StorageStatsService extends IStorageStatsManager.Stub { public long getFreeBytes(String volumeUuid, String callingPackage) { // NOTE: No permissions required - long cacheBytes = 0; final long token = Binder.clearCallingIdentity(); try { + final File path; + try { + path = mStorage.findPathForUuid(volumeUuid); + } catch (FileNotFoundException e) { + throw new ParcelableException(e); + } + + // Free space is usable bytes plus any cached data that we're + // willing to automatically clear. To avoid user confusion, this + // logic should be kept in sync with getAllocatableBytes(). if (isQuotaSupported(volumeUuid, callingPackage)) { - for (UserInfo user : mUser.getUsers()) { - final StorageStats stats = queryStatsForUser(volumeUuid, user.id, null); - cacheBytes += stats.cacheBytes; - } + final long cacheTotal = getCacheBytes(volumeUuid, callingPackage); + final long cacheReserved = mStorage.getStorageCacheBytes(path); + final long cacheClearable = Math.max(0, cacheTotal - cacheReserved); + + return path.getUsableSpace() + cacheClearable; + } else { + return path.getUsableSpace(); } } finally { Binder.restoreCallingIdentity(token); } + } - if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) { - return Environment.getDataDirectory().getFreeSpace() + cacheBytes; - } else { - final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid); - if (vol == null) { - throw new ParcelableException( - new IOException("Failed to find storage device for UUID " + volumeUuid)); - } - return vol.getPath().getFreeSpace() + cacheBytes; + @Override + public long getCacheBytes(String volumeUuid, String callingPackage) { + enforcePermission(Binder.getCallingUid(), callingPackage); + + long cacheBytes = 0; + for (UserInfo user : mUser.getUsers()) { + final StorageStats stats = queryStatsForUser(volumeUuid, user.id, null); + cacheBytes += stats.cacheBytes; } + return cacheBytes; } @Override diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index bc5e4d51e0f8..fa7b9b0b96f0 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1449,6 +1449,11 @@ public class PhoneNumberUtils * @hide */ public static boolean isInternationalNumber(String phoneNumber, String defaultCountryIso) { + // If no phone number is provided, it can't be international. + if (TextUtils.isEmpty(phoneNumber)) { + return false; + } + // If it starts with # or * its not international. if (phoneNumber.startsWith("#") || phoneNumber.startsWith("*")) { return false; diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index bf189492b082..b2f1f62647e6 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -160,7 +160,7 @@ cc_library_host_shared { cc_test_host { name: "aapt2_tests", srcs: ["**/*_test.cpp"], - static_libs: ["libaapt2"], + static_libs: ["libaapt2", "libgmock"], defaults: ["aapt_defaults"], } diff --git a/tools/aapt2/Format.proto b/tools/aapt2/Format.proto index 0917129ba90d..870b735f70a7 100644 --- a/tools/aapt2/Format.proto +++ b/tools/aapt2/Format.proto @@ -69,6 +69,7 @@ message SymbolStatus { optional Visibility visibility = 1; optional Source source = 2; optional string comment = 3; + optional bool allow_new = 4; } message Entry { diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 0d1850fed26a..57ae2700127c 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -92,14 +92,14 @@ struct ParsedResource { Source source; ResourceId id; Maybe<SymbolState> symbol_state; + bool allow_new = false; std::string comment; std::unique_ptr<Value> value; std::list<ParsedResource> child_resources; }; // Recursively adds resources to the ResourceTable. -static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, - ParsedResource* res) { +static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, ParsedResource* res) { StringPiece trimmed_comment = util::TrimWhitespace(res->comment); if (trimmed_comment.size() != res->comment.size()) { // Only if there was a change do we re-assign. @@ -111,6 +111,7 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, symbol.state = res->symbol_state.value(); symbol.source = res->source; symbol.comment = res->comment; + symbol.allow_new = res->allow_new; if (!table->SetSymbolState(res->name, res->id, symbol, diag)) { return false; } @@ -121,8 +122,8 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, res->value->SetComment(std::move(res->comment)); res->value->SetSource(std::move(res->source)); - if (!table->AddResource(res->name, res->id, res->config, res->product, - std::move(res->value), diag)) { + if (!table->AddResource(res->name, res->id, res->config, res->product, std::move(res->value), + diag)) { return false; } } @@ -849,6 +850,7 @@ bool ResourceParser::ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource) { if (ParseSymbolImpl(parser, out_resource)) { out_resource->symbol_state = SymbolState::kUndefined; + out_resource->allow_new = true; return true; } return false; diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index faa660729237..e3abde6bef29 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -777,8 +777,7 @@ TEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) { ASSERT_FALSE(TestParse(input)); } -TEST_F(ResourceParserTest, - AddResourcesElementShouldAddEntryWithUndefinedSymbol) { +TEST_F(ResourceParserTest, AddResourcesElementShouldAddEntryWithUndefinedSymbol) { std::string input = R"EOF(<add-resource name="bar" type="string" />)EOF"; ASSERT_TRUE(TestParse(input)); @@ -788,6 +787,7 @@ TEST_F(ResourceParserTest, const ResourceEntry* entry = result.value().entry; ASSERT_NE(nullptr, entry); EXPECT_EQ(SymbolState::kUndefined, entry->symbol_status.state); + EXPECT_TRUE(entry->symbol_status.allow_new); } TEST_F(ResourceParserTest, ParseItemElementWithFormat) { diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index 1947628e9267..168004f0b721 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -440,8 +440,7 @@ bool ResourceTable::AddResourceImpl(const ResourceNameRef& name, const ResourceI return true; } -bool ResourceTable::SetSymbolState(const ResourceNameRef& name, - const ResourceId& res_id, +bool ResourceTable::SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id, const Symbol& symbol, IDiagnostics* diag) { return SetSymbolStateImpl(name, res_id, symbol, ValidateName, diag); } @@ -489,8 +488,7 @@ bool ResourceTable::SetSymbolStateImpl(const ResourceNameRef& name, const Resour diag->Error(DiagMessage(symbol.source) << "trying to add resource '" << name << "' with ID " << res_id << " but resource already has ID " - << ResourceId(package->id.value(), type->id.value(), - entry->id.value())); + << ResourceId(package->id.value(), type->id.value(), entry->id.value())); return false; } @@ -505,6 +503,11 @@ bool ResourceTable::SetSymbolStateImpl(const ResourceNameRef& name, const Resour type->symbol_status.state = SymbolState::kPublic; } + if (symbol.allow_new) { + // This symbol can be added as a new resource when merging (if it belongs to an overlay). + entry->symbol_status.allow_new = true; + } + if (symbol.state == SymbolState::kUndefined && entry->symbol_status.state != SymbolState::kUndefined) { // We can't undefine a symbol (remove its visibility). Ignore. @@ -517,7 +520,10 @@ bool ResourceTable::SetSymbolStateImpl(const ResourceNameRef& name, const Resour return true; } - entry->symbol_status = std::move(symbol); + // This symbol definition takes precedence, replace. + entry->symbol_status.state = symbol.state; + entry->symbol_status.source = symbol.source; + entry->symbol_status.comment = symbol.comment; return true; } diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index b0321214c6cc..4295d0674774 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -50,6 +50,10 @@ enum class SymbolState { struct Symbol { SymbolState state = SymbolState::kUndefined; Source source; + + // Whether this entry (originating from an overlay) can be added as a new resource. + bool allow_new = false; + std::string comment; }; @@ -223,8 +227,7 @@ class ResourceTable { bool SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id, const Symbol& symbol, IDiagnostics* diag); - bool SetSymbolStateAllowMangled(const ResourceNameRef& name, - const ResourceId& res_id, + bool SetSymbolStateAllowMangled(const ResourceNameRef& name, const ResourceId& res_id, const Symbol& symbol, IDiagnostics* diag); struct SearchResult { diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index 1bb7d9beee45..818c8cec30f9 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -496,19 +496,17 @@ Maybe<int> ParseSdkVersion(const StringPiece& str) { std::unique_ptr<BinaryPrimitive> TryParseBool(const StringPiece& str) { if (Maybe<bool> maybe_result = ParseBool(str)) { - android::Res_value value = {}; - value.dataType = android::Res_value::TYPE_INT_BOOLEAN; - - if (maybe_result.value()) { - value.data = 0xffffffffu; - } else { - value.data = 0; - } - return util::make_unique<BinaryPrimitive>(value); + const uint32_t data = maybe_result.value() ? 0xffffffffu : 0u; + return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_BOOLEAN, data); } return {}; } +std::unique_ptr<BinaryPrimitive> MakeBool(bool val) { + return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_BOOLEAN, + val ? 0xffffffffu : 0u); +} + std::unique_ptr<BinaryPrimitive> TryParseInt(const StringPiece& str) { std::u16string str16 = util::Utf8ToUtf16(str); android::Res_value value; diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h index 48922b72fefa..da0fc8ee314a 100644 --- a/tools/aapt2/ResourceUtils.h +++ b/tools/aapt2/ResourceUtils.h @@ -147,6 +147,9 @@ std::unique_ptr<BinaryPrimitive> TryParseColor(const android::StringPiece& str); */ std::unique_ptr<BinaryPrimitive> TryParseBool(const android::StringPiece& str); +// Returns a boolean BinaryPrimitive. +std::unique_ptr<BinaryPrimitive> MakeBool(bool val); + /* * Returns a BinaryPrimitve object representing an integer if the string was * parsed as one. diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp index 34bd2b4361ca..abfdec48df67 100644 --- a/tools/aapt2/ResourceValues.cpp +++ b/tools/aapt2/ResourceValues.cpp @@ -29,6 +29,11 @@ namespace aapt { +std::ostream& operator<<(std::ostream& out, const Value& value) { + value.Print(&out); + return out; +} + template <typename Derived> void BaseValue<Derived>::Accept(RawValueVisitor* visitor) { visitor->Visit(static_cast<Derived*>(this)); @@ -346,6 +351,15 @@ Attribute::Attribute(bool w, uint32_t t) weak_ = w; } +std::ostream& operator<<(std::ostream& out, const Attribute::Symbol& s) { + if (s.symbol.name) { + out << s.symbol.name.value().entry; + } else { + out << "???"; + } + return out << "=" << s.value; +} + template <typename T> constexpr T* add_pointer(T& val) { return &val; @@ -361,31 +375,27 @@ bool Attribute::Equals(const Value* value) const { return false; } - if (type_mask != other->type_mask || min_int != other->min_int || - max_int != other->max_int) { + if (type_mask != other->type_mask || min_int != other->min_int || max_int != other->max_int) { return false; } std::vector<const Symbol*> sorted_a; std::transform(symbols.begin(), symbols.end(), std::back_inserter(sorted_a), add_pointer<const Symbol>); - std::sort(sorted_a.begin(), sorted_a.end(), - [](const Symbol* a, const Symbol* b) -> bool { - return a->symbol.name < b->symbol.name; - }); + std::sort(sorted_a.begin(), sorted_a.end(), [](const Symbol* a, const Symbol* b) -> bool { + return a->symbol.name < b->symbol.name; + }); std::vector<const Symbol*> sorted_b; - std::transform(other->symbols.begin(), other->symbols.end(), - std::back_inserter(sorted_b), add_pointer<const Symbol>); - std::sort(sorted_b.begin(), sorted_b.end(), - [](const Symbol* a, const Symbol* b) -> bool { - return a->symbol.name < b->symbol.name; - }); + std::transform(other->symbols.begin(), other->symbols.end(), std::back_inserter(sorted_b), + add_pointer<const Symbol>); + std::sort(sorted_b.begin(), sorted_b.end(), [](const Symbol* a, const Symbol* b) -> bool { + return a->symbol.name < b->symbol.name; + }); return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(), [](const Symbol* a, const Symbol* b) -> bool { - return a->symbol.Equals(&b->symbol) && - a->value == b->value; + return a->symbol.Equals(&b->symbol) && a->value == b->value; }); } @@ -588,14 +598,50 @@ bool Attribute::Matches(const Item* item, DiagMessage* out_msg) const { return true; } +std::ostream& operator<<(std::ostream& out, const Style::Entry& entry) { + if (entry.key.name) { + out << entry.key.name.value(); + } else if (entry.key.id) { + out << entry.key.id.value(); + } else { + out << "???"; + } + out << " = " << entry.value; + return out; +} + +template <typename T> +std::vector<T*> ToPointerVec(std::vector<T>& src) { + std::vector<T*> dst; + dst.reserve(src.size()); + for (T& in : src) { + dst.push_back(&in); + } + return dst; +} + +template <typename T> +std::vector<const T*> ToPointerVec(const std::vector<T>& src) { + std::vector<const T*> dst; + dst.reserve(src.size()); + for (const T& in : src) { + dst.push_back(&in); + } + return dst; +} + +static bool KeyNameComparator(const Style::Entry* a, const Style::Entry* b) { + return a->key.name < b->key.name; +} + bool Style::Equals(const Value* value) const { const Style* other = ValueCast<Style>(value); if (!other) { return false; } + if (bool(parent) != bool(other->parent) || - (parent && other->parent && - !parent.value().Equals(&other->parent.value()))) { + (parent && other->parent && !parent.value().Equals(&other->parent.value()))) { return false; } @@ -603,26 +649,15 @@ bool Style::Equals(const Value* value) const { return false; } - std::vector<const Entry*> sorted_a; - std::transform(entries.begin(), entries.end(), std::back_inserter(sorted_a), - add_pointer<const Entry>); - std::sort(sorted_a.begin(), sorted_a.end(), - [](const Entry* a, const Entry* b) -> bool { - return a->key.name < b->key.name; - }); + std::vector<const Entry*> sorted_a = ToPointerVec(entries); + std::sort(sorted_a.begin(), sorted_a.end(), KeyNameComparator); - std::vector<const Entry*> sorted_b; - std::transform(other->entries.begin(), other->entries.end(), - std::back_inserter(sorted_b), add_pointer<const Entry>); - std::sort(sorted_b.begin(), sorted_b.end(), - [](const Entry* a, const Entry* b) -> bool { - return a->key.name < b->key.name; - }); + std::vector<const Entry*> sorted_b = ToPointerVec(other->entries); + std::sort(sorted_b.begin(), sorted_b.end(), KeyNameComparator); return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(), [](const Entry* a, const Entry* b) -> bool { - return a->key.Equals(&b->key) && - a->value->Equals(b->value.get()); + return a->key.Equals(&b->key) && a->value->Equals(b->value.get()); }); } @@ -633,8 +668,7 @@ Style* Style::Clone(StringPool* new_pool) const { style->comment_ = comment_; style->source_ = source_; for (auto& entry : entries) { - style->entries.push_back( - Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))}); + style->entries.push_back(Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))}); } return style; } @@ -642,26 +676,73 @@ Style* Style::Clone(StringPool* new_pool) const { void Style::Print(std::ostream* out) const { *out << "(style) "; if (parent && parent.value().name) { - if (parent.value().private_reference) { + const Reference& parent_ref = parent.value(); + if (parent_ref.private_reference) { *out << "*"; } - *out << parent.value().name.value(); + *out << parent_ref.name.value(); } *out << " [" << util::Joiner(entries, ", ") << "]"; } -static ::std::ostream& operator<<(::std::ostream& out, - const Style::Entry& value) { - if (value.key.name) { - out << value.key.name.value(); - } else if (value.key.id) { - out << value.key.id.value(); - } else { - out << "???"; +Style::Entry CloneEntry(const Style::Entry& entry, StringPool* pool) { + Style::Entry cloned_entry{entry.key}; + if (entry.value != nullptr) { + cloned_entry.value.reset(entry.value->Clone(pool)); } - out << " = "; - value.value->Print(&out); - return out; + return cloned_entry; +} + +void Style::MergeWith(Style* other, StringPool* pool) { + if (other->parent) { + parent = other->parent; + } + + // We can't assume that the entries are sorted alphabetically since they're supposed to be + // sorted by Resource Id. Not all Resource Ids may be set though, so we can't sort and merge + // them keying off that. + // + // Instead, sort the entries of each Style by their name in a separate structure. Then merge + // those. + + std::vector<Entry*> this_sorted = ToPointerVec(entries); + std::sort(this_sorted.begin(), this_sorted.end(), KeyNameComparator); + + std::vector<Entry*> other_sorted = ToPointerVec(other->entries); + std::sort(other_sorted.begin(), other_sorted.end(), KeyNameComparator); + + auto this_iter = this_sorted.begin(); + const auto this_end = this_sorted.end(); + + auto other_iter = other_sorted.begin(); + const auto other_end = other_sorted.end(); + + std::vector<Entry> merged_entries; + while (this_iter != this_end) { + if (other_iter != other_end) { + if ((*this_iter)->key.name < (*other_iter)->key.name) { + merged_entries.push_back(std::move(**this_iter)); + ++this_iter; + } else { + // The other overrides. + merged_entries.push_back(CloneEntry(**other_iter, pool)); + if ((*this_iter)->key.name == (*other_iter)->key.name) { + ++this_iter; + } + ++other_iter; + } + } else { + merged_entries.push_back(std::move(**this_iter)); + ++this_iter; + } + } + + while (other_iter != other_end) { + merged_entries.push_back(CloneEntry(**other_iter, pool)); + ++other_iter; + } + + entries = std::move(merged_entries); } bool Array::Equals(const Value* value) const { @@ -758,11 +839,6 @@ void Plural::Print(std::ostream* out) const { } } -static ::std::ostream& operator<<(::std::ostream& out, - const std::unique_ptr<Item>& item) { - return out << *item; -} - bool Styleable::Equals(const Value* value) const { const Styleable* other = ValueCast<Styleable>(value); if (!other) { @@ -810,8 +886,7 @@ struct NameOnlyComparator { void Styleable::MergeWith(Styleable* other) { // Compare only names, because some References may already have their IDs - // assigned - // (framework IDs that don't change). + // assigned (framework IDs that don't change). std::set<Reference, NameOnlyComparator> references; references.insert(entries.begin(), entries.end()); references.insert(other->entries.begin(), other->entries.end()); diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h index 06f949f9555c..ac5795fb9774 100644 --- a/tools/aapt2/ResourceValues.h +++ b/tools/aapt2/ResourceValues.h @@ -40,7 +40,8 @@ struct RawValueVisitor; // type specific operations is to check the Value's type() and // cast it to the appropriate subclass. This isn't super clean, // but it is the simplest strategy. -struct Value { +class Value { + public: virtual ~Value() = default; // Whether this value is weak and can be overridden without warning or error. Default is false. @@ -82,6 +83,8 @@ struct Value { // Human readable printout of this value. virtual void Print(std::ostream* out) const = 0; + friend std::ostream& operator<<(std::ostream& out, const Value& value); + protected: Source source_; std::string comment_; @@ -245,6 +248,8 @@ struct Attribute : public BaseValue<Attribute> { struct Symbol { Reference symbol; uint32_t value; + + friend std::ostream& operator<<(std::ostream& out, const Symbol& symbol); }; uint32_t type_mask; @@ -266,6 +271,8 @@ struct Style : public BaseValue<Style> { struct Entry { Reference key; std::unique_ptr<Item> value; + + friend std::ostream& operator<<(std::ostream& out, const Entry& entry); }; Maybe<Reference> parent; @@ -278,6 +285,10 @@ struct Style : public BaseValue<Style> { bool Equals(const Value* value) const override; Style* Clone(StringPool* new_pool) const override; void Print(std::ostream* out) const override; + + // Merges `style` into this Style. All identical attributes of `style` take precedence, including + // the parent, if there is one. + void MergeWith(Style* style, StringPool* pool); }; struct Array : public BaseValue<Array> { @@ -307,20 +318,15 @@ struct Styleable : public BaseValue<Styleable> { void MergeWith(Styleable* styleable); }; -// Stream operator for printing Value objects. -inline ::std::ostream& operator<<(::std::ostream& out, const Value& value) { - value.Print(&out); - return out; -} - -inline ::std::ostream& operator<<(::std::ostream& out, - const Attribute::Symbol& s) { - if (s.symbol.name) { - out << s.symbol.name.value().entry; +template <typename T> +typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type operator<<( + std::ostream& out, const std::unique_ptr<T>& value) { + if (value == nullptr) { + out << "NULL"; } else { - out << "???"; + value->Print(&out); } - return out << "=" << s.value; + return out; } } // namespace aapt diff --git a/tools/aapt2/ResourceValues_test.cpp b/tools/aapt2/ResourceValues_test.cpp index 692258003471..e154d93b6f85 100644 --- a/tools/aapt2/ResourceValues_test.cpp +++ b/tools/aapt2/ResourceValues_test.cpp @@ -148,4 +148,36 @@ TEST(ResourceValuesTest, StyleClone) { EXPECT_TRUE(a->Equals(b.get())); } +TEST(ResourceValuesTest, StyleMerges) { + StringPool pool_a; + StringPool pool_b; + + std::unique_ptr<Style> a = + test::StyleBuilder() + .SetParent("android:style/Parent") + .AddItem("android:attr/a", util::make_unique<String>(pool_a.MakeRef("FooA"))) + .AddItem("android:attr/b", util::make_unique<String>(pool_a.MakeRef("FooB"))) + .Build(); + + std::unique_ptr<Style> b = + test::StyleBuilder() + .SetParent("android:style/OverlayParent") + .AddItem("android:attr/c", util::make_unique<String>(pool_b.MakeRef("OverlayFooC"))) + .AddItem("android:attr/a", util::make_unique<String>(pool_b.MakeRef("OverlayFooA"))) + .Build(); + + a->MergeWith(b.get(), &pool_a); + + StringPool pool; + std::unique_ptr<Style> expected = + test::StyleBuilder() + .SetParent("android:style/OverlayParent") + .AddItem("android:attr/a", util::make_unique<String>(pool.MakeRef("OverlayFooA"))) + .AddItem("android:attr/b", util::make_unique<String>(pool.MakeRef("FooB"))) + .AddItem("android:attr/c", util::make_unique<String>(pool.MakeRef("OverlayFooC"))) + .Build(); + + EXPECT_TRUE(a->Equals(expected.get())); +} + } // namespace aapt diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index dd4b2ba9ff16..740a401f9b57 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -440,7 +440,8 @@ static bool IsTransitionElement(const std::string& name) { } static bool IsVectorElement(const std::string& name) { - return name == "vector" || name == "animated-vector"; + return name == "vector" || name == "animated-vector" || name == "pathInterpolator" || + name == "objectAnimator"; } template <typename T> diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index 931109125263..10e837c725e5 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -179,32 +179,39 @@ static bool MergeEntry(IAaptContext* context, const Source& src, return true; } -/** - * Modified CollisionResolver which will merge Styleables. Used with overlays. - * - * Styleables are not actual resources, but they are treated as such during the - * compilation phase. Styleables don't simply overlay each other, their - * definitions merge - * and accumulate. If both values are Styleables, we just merge them into the - * existing value. - */ -static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing, - Value* incoming) { +// Modified CollisionResolver which will merge Styleables and Styles. Used with overlays. +// +// Styleables are not actual resources, but they are treated as such during the +// compilation phase. +// +// Styleables and Styles don't simply overlay each other, their definitions merge +// and accumulate. If both values are Styleables/Styles, we just merge them into the +// existing value. +static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing, Value* incoming, + StringPool* pool) { if (Styleable* existing_styleable = ValueCast<Styleable>(existing)) { if (Styleable* incoming_styleable = ValueCast<Styleable>(incoming)) { // Styleables get merged. existing_styleable->MergeWith(incoming_styleable); return ResourceTable::CollisionResult::kKeepOriginal; } + } else if (Style* existing_style = ValueCast<Style>(existing)) { + if (Style* incoming_style = ValueCast<Style>(incoming)) { + // Styles get merged. + existing_style->MergeWith(incoming_style, pool); + return ResourceTable::CollisionResult::kKeepOriginal; + } } // Delegate to the default handler. return ResourceTable::ResolveValueCollision(existing, incoming); } -static ResourceTable::CollisionResult MergeConfigValue( - IAaptContext* context, const ResourceNameRef& res_name, const bool overlay, - ResourceConfigValue* dst_config_value, - ResourceConfigValue* src_config_value) { +static ResourceTable::CollisionResult MergeConfigValue(IAaptContext* context, + const ResourceNameRef& res_name, + const bool overlay, + ResourceConfigValue* dst_config_value, + ResourceConfigValue* src_config_value, + StringPool* pool) { using CollisionResult = ResourceTable::CollisionResult; Value* dst_value = dst_config_value->value.get(); @@ -212,10 +219,9 @@ static ResourceTable::CollisionResult MergeConfigValue( CollisionResult collision_result; if (overlay) { - collision_result = ResolveMergeCollision(dst_value, src_value); + collision_result = ResolveMergeCollision(dst_value, src_value, pool); } else { - collision_result = - ResourceTable::ResolveValueCollision(dst_value, src_value); + collision_result = ResourceTable::ResolveValueCollision(dst_value, src_value); } if (collision_result == CollisionResult::kConflict) { @@ -224,10 +230,9 @@ static ResourceTable::CollisionResult MergeConfigValue( } // Error! - context->GetDiagnostics()->Error( - DiagMessage(src_value->GetSource()) - << "resource '" << res_name << "' has a conflicting value for " - << "configuration (" << src_config_value->config << ")"); + context->GetDiagnostics()->Error(DiagMessage(src_value->GetSource()) + << "resource '" << res_name << "' has a conflicting value for " + << "configuration (" << src_config_value->config << ")"); context->GetDiagnostics()->Note(DiagMessage(dst_value->GetSource()) << "originally defined here"); return CollisionResult::kConflict; @@ -243,8 +248,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table, bool error = false; for (auto& src_type : src_package->types) { - ResourceTableType* dst_type = - master_package_->FindOrCreateType(src_type->type); + ResourceTableType* dst_type = master_package_->FindOrCreateType(src_type->type); if (!MergeType(context_, src, dst_type, src_type.get())) { error = true; continue; @@ -253,27 +257,24 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table, for (auto& src_entry : src_type->entries) { std::string entry_name = src_entry->name; if (mangle_package) { - entry_name = - NameMangler::MangleEntry(src_package->name, src_entry->name); + entry_name = NameMangler::MangleEntry(src_package->name, src_entry->name); } ResourceEntry* dst_entry; - if (allow_new_resources) { + if (allow_new_resources || src_entry->symbol_status.allow_new) { dst_entry = dst_type->FindOrCreateEntry(entry_name); } else { dst_entry = dst_type->FindEntry(entry_name); } - const ResourceNameRef res_name(src_package->name, src_type->type, - src_entry->name); + const ResourceNameRef res_name(src_package->name, src_type->type, src_entry->name); if (!dst_entry) { - context_->GetDiagnostics()->Error( - DiagMessage(src) << "resource " << res_name - << " does not override an existing resource"); - context_->GetDiagnostics()->Note( - DiagMessage(src) << "define an <add-resource> tag or use " - << "--auto-add-overlay"); + context_->GetDiagnostics()->Error(DiagMessage(src) + << "resource " << res_name + << " does not override an existing resource"); + context_->GetDiagnostics()->Note(DiagMessage(src) << "define an <add-resource> tag or use " + << "--auto-add-overlay"); error = true; continue; } @@ -291,7 +292,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table, if (dst_config_value) { CollisionResult collision_result = MergeConfigValue(context_, res_name, overlay, dst_config_value, - src_config_value.get()); + src_config_value.get(), &master_table_->string_pool); if (collision_result == CollisionResult::kConflict) { error = true; continue; @@ -299,25 +300,22 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table, continue; } } else { - dst_config_value = dst_entry->FindOrCreateValue( - src_config_value->config, src_config_value->product); + dst_config_value = + dst_entry->FindOrCreateValue(src_config_value->config, src_config_value->product); } // Continue if we're taking the new resource. - if (FileReference* f = - ValueCast<FileReference>(src_config_value->value.get())) { + if (FileReference* f = ValueCast<FileReference>(src_config_value->value.get())) { std::unique_ptr<FileReference> new_file_ref; if (mangle_package) { new_file_ref = CloneAndMangleFile(src_package->name, *f); } else { - new_file_ref = std::unique_ptr<FileReference>( - f->Clone(&master_table_->string_pool)); + new_file_ref = std::unique_ptr<FileReference>(f->Clone(&master_table_->string_pool)); } if (callback) { - if (!callback(res_name, src_config_value->config, - new_file_ref.get(), f)) { + if (!callback(res_name, src_config_value->config, new_file_ref.get(), f)) { error = true; continue; } @@ -341,18 +339,15 @@ std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile( std::string mangled_entry = NameMangler::MangleEntry(package, entry.to_string()); std::string newPath = prefix.to_string() + mangled_entry + suffix.to_string(); std::unique_ptr<FileReference> new_file_ref = - util::make_unique<FileReference>( - master_table_->string_pool.MakeRef(newPath)); + util::make_unique<FileReference>(master_table_->string_pool.MakeRef(newPath)); new_file_ref->SetComment(file_ref.GetComment()); new_file_ref->SetSource(file_ref.GetSource()); return new_file_ref; } - return std::unique_ptr<FileReference>( - file_ref.Clone(&master_table_->string_pool)); + return std::unique_ptr<FileReference>(file_ref.Clone(&master_table_->string_pool)); } -bool TableMerger::MergeFileImpl(const ResourceFile& file_desc, io::IFile* file, - bool overlay) { +bool TableMerger::MergeFileImpl(const ResourceFile& file_desc, io::IFile* file, bool overlay) { ResourceTable table; std::string path = ResourceUtils::BuildResourceFileName(file_desc); std::unique_ptr<FileReference> file_ref = diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp index 742f5a7a570a..45b01a494164 100644 --- a/tools/aapt2/link/TableMerger_test.cpp +++ b/tools/aapt2/link/TableMerger_test.cpp @@ -20,6 +20,14 @@ #include "io/FileSystem.h" #include "test/Test.h" +using ::aapt::test::ValueEq; +using ::testing::Contains; +using ::testing::NotNull; +using ::testing::UnorderedElementsAreArray; +using ::testing::Pointee; +using ::testing::Field; +using ::testing::Eq; + namespace aapt { struct TableMergerTest : public ::testing::Test { @@ -62,26 +70,20 @@ TEST_F(TableMergerTest, SimpleMerge) { io::FileCollection collection; ASSERT_TRUE(merger.Merge({}, table_a.get())); - ASSERT_TRUE( - merger.MergeAndMangle({}, "com.app.b", table_b.get(), &collection)); + ASSERT_TRUE(merger.MergeAndMangle({}, "com.app.b", table_b.get(), &collection)); EXPECT_TRUE(merger.merged_packages().count("com.app.b") != 0); // Entries from com.app.a should not be mangled. - AAPT_EXPECT_TRUE( - final_table.FindResource(test::ParseNameOrDie("com.app.a:id/foo"))); - AAPT_EXPECT_TRUE( - final_table.FindResource(test::ParseNameOrDie("com.app.a:id/bar"))); - AAPT_EXPECT_TRUE(final_table.FindResource( - test::ParseNameOrDie("com.app.a:styleable/view"))); + EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:id/foo"))); + EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:id/bar"))); + EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:styleable/view"))); // The unmangled name should not be present. - AAPT_EXPECT_FALSE( - final_table.FindResource(test::ParseNameOrDie("com.app.b:id/foo"))); + EXPECT_FALSE(final_table.FindResource(test::ParseNameOrDie("com.app.b:id/foo"))); // Look for the mangled name. - AAPT_EXPECT_TRUE(final_table.FindResource( - test::ParseNameOrDie("com.app.a:id/com.app.b$foo"))); + EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:id/com.app.b$foo"))); } TEST_F(TableMergerTest, MergeFile) { @@ -100,7 +102,7 @@ TEST_F(TableMergerTest, MergeFile) { FileReference* file = test::GetValueForConfig<FileReference>( &final_table, "com.app.a:layout/main", test::ParseConfigOrDie("hdpi-v4")); - ASSERT_NE(nullptr, file); + ASSERT_THAT(file, NotNull()); EXPECT_EQ(std::string("res/layout-hdpi-v4/main.xml"), *file->path); } @@ -137,17 +139,14 @@ TEST_F(TableMergerTest, MergeFileReferences) { collection.InsertFile("res/xml/file.xml"); ASSERT_TRUE(merger.Merge({}, table_a.get())); - ASSERT_TRUE( - merger.MergeAndMangle({}, "com.app.b", table_b.get(), &collection)); + ASSERT_TRUE(merger.MergeAndMangle({}, "com.app.b", table_b.get(), &collection)); - FileReference* f = - test::GetValue<FileReference>(&final_table, "com.app.a:xml/file"); - ASSERT_NE(f, nullptr); + FileReference* f = test::GetValue<FileReference>(&final_table, "com.app.a:xml/file"); + ASSERT_THAT(f, NotNull()); EXPECT_EQ(std::string("res/xml/file.xml"), *f->path); - f = test::GetValue<FileReference>(&final_table, - "com.app.a:xml/com.app.b$file"); - ASSERT_NE(f, nullptr); + f = test::GetValue<FileReference>(&final_table, "com.app.a:xml/com.app.b$file"); + ASSERT_THAT(f, NotNull()); EXPECT_EQ(std::string("res/xml/com.app.b$file.xml"), *f->path); } @@ -171,10 +170,9 @@ TEST_F(TableMergerTest, OverrideResourceWithOverlay) { ASSERT_TRUE(merger.Merge({}, base.get())); ASSERT_TRUE(merger.MergeOverlay({}, overlay.get())); - BinaryPrimitive* foo = - test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/foo"); - ASSERT_NE(nullptr, foo); - EXPECT_EQ(0x0u, foo->value.data); + BinaryPrimitive* foo = test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/foo"); + ASSERT_THAT(foo, + Pointee(Field(&BinaryPrimitive::value, Field(&android::Res_value::data, Eq(0u))))); } TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) { @@ -248,18 +246,18 @@ TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) { TEST_F(TableMergerTest, MergeAddResourceFromOverlay) { std::unique_ptr<ResourceTable> table_a = - test::ResourceTableBuilder() - .SetPackageId("", 0x7f) - .SetSymbolState("bool/foo", {}, SymbolState::kUndefined) - .Build(); + test::ResourceTableBuilder().SetPackageId("", 0x7f).Build(); std::unique_ptr<ResourceTable> table_b = test::ResourceTableBuilder() .SetPackageId("", 0x7f) + .SetSymbolState("bool/foo", {}, SymbolState::kUndefined, true /*allow new overlay*/) .AddValue("bool/foo", ResourceUtils::TryParseBool("true")) .Build(); ResourceTable final_table; - TableMerger merger(context_.get(), &final_table, TableMergerOptions{}); + TableMergerOptions options; + options.auto_add_overlay = false; + TableMerger merger(context_.get(), &final_table, options); ASSERT_TRUE(merger.Merge({}, table_a.get())); ASSERT_TRUE(merger.MergeOverlay({}, table_b.get())); @@ -301,7 +299,7 @@ TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) { ASSERT_FALSE(merger.MergeOverlay({}, table_b.get())); } -TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) { +TEST_F(TableMergerTest, OverlaidStyleablesAndStylesShouldBeMerged) { std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -310,15 +308,27 @@ TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) { .AddItem("com.app.a:attr/bar") .AddItem("com.app.a:attr/foo", ResourceId(0x01010000)) .Build()) + .AddValue("com.app.a:style/Theme", + test::StyleBuilder() + .SetParent("com.app.a:style/Parent") + .AddItem("com.app.a:attr/bar", util::make_unique<Id>()) + .AddItem("com.app.a:attr/foo", ResourceUtils::MakeBool(false)) + .Build()) .Build(); std::unique_ptr<ResourceTable> table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) - .AddValue("com.app.a:styleable/Foo", - test::StyleableBuilder() - .AddItem("com.app.a:attr/bat") - .AddItem("com.app.a:attr/foo") + .AddValue("com.app.a:styleable/Foo", test::StyleableBuilder() + .AddItem("com.app.a:attr/bat") + .AddItem("com.app.a:attr/foo") + .Build()) + .AddValue("com.app.a:style/Theme", + test::StyleBuilder() + .SetParent("com.app.a:style/OverlayParent") + .AddItem("com.app.a:attr/bat", util::make_unique<Id>()) + .AddItem("com.app.a:attr/foo", ResourceId(0x01010000), + ResourceUtils::MakeBool(true)) .Build()) .Build(); @@ -330,18 +340,29 @@ TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) { ASSERT_TRUE(merger.Merge({}, table_a.get())); ASSERT_TRUE(merger.MergeOverlay({}, table_b.get())); - Styleable* styleable = - test::GetValue<Styleable>(&final_table, "com.app.a:styleable/Foo"); - ASSERT_NE(nullptr, styleable); + Styleable* styleable = test::GetValue<Styleable>(&final_table, "com.app.a:styleable/Foo"); + ASSERT_THAT(styleable, NotNull()); std::vector<Reference> expected_refs = { Reference(test::ParseNameOrDie("com.app.a:attr/bar")), Reference(test::ParseNameOrDie("com.app.a:attr/bat")), - Reference(test::ParseNameOrDie("com.app.a:attr/foo"), - ResourceId(0x01010000)), + Reference(test::ParseNameOrDie("com.app.a:attr/foo"), ResourceId(0x01010000)), }; + EXPECT_THAT(styleable->entries, UnorderedElementsAreArray(expected_refs)); + + Style* style = test::GetValue<Style>(&final_table, "com.app.a:style/Theme"); + ASSERT_THAT(style, NotNull()); + + std::vector<Reference> extracted_refs; + for (const auto& entry : style->entries) { + extracted_refs.push_back(entry.key); + } + EXPECT_THAT(extracted_refs, UnorderedElementsAreArray(expected_refs)); - EXPECT_EQ(expected_refs, styleable->entries); + const auto expected = ResourceUtils::MakeBool(true); + EXPECT_THAT(style->entries, Contains(Field(&Style::Entry::value, Pointee(ValueEq(*expected))))); + EXPECT_THAT(style->parent, + Eq(make_value(Reference(test::ParseNameOrDie("com.app.a:style/OverlayParent"))))); } } // namespace aapt diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp index d93d495b106f..1d0041b2ac5a 100644 --- a/tools/aapt2/proto/TableProtoDeserializer.cpp +++ b/tools/aapt2/proto/TableProtoDeserializer.cpp @@ -32,8 +32,7 @@ class ReferenceIdToNameVisitor : public ValueVisitor { public: using ValueVisitor::Visit; - explicit ReferenceIdToNameVisitor( - const std::map<ResourceId, ResourceNameRef>* mapping) + explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping) : mapping_(mapping) { CHECK(mapping_ != nullptr); } @@ -75,13 +74,11 @@ class PackagePbDeserializer { std::map<ResourceId, ResourceNameRef> idIndex; - ResourceTablePackage* pkg = - table->CreatePackage(pbPackage.package_name(), id); + ResourceTablePackage* pkg = table->CreatePackage(pbPackage.package_name(), id); for (const pb::Type& pbType : pbPackage.types()) { const ResourceType* resType = ParseResourceType(pbType.name()); if (!resType) { - diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name() - << "'"); + diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name() << "'"); return {}; } @@ -95,21 +92,20 @@ class PackagePbDeserializer { if (pbEntry.has_symbol_status()) { const pb::SymbolStatus& pbStatus = pbEntry.symbol_status(); if (pbStatus.has_source()) { - DeserializeSourceFromPb(pbStatus.source(), *source_pool_, - &entry->symbol_status.source); + DeserializeSourceFromPb(pbStatus.source(), *source_pool_, &entry->symbol_status.source); } if (pbStatus.has_comment()) { entry->symbol_status.comment = pbStatus.comment(); } - SymbolState visibility = - DeserializeVisibilityFromPb(pbStatus.visibility()); + entry->symbol_status.allow_new = pbStatus.allow_new(); + + SymbolState visibility = DeserializeVisibilityFromPb(pbStatus.visibility()); entry->symbol_status.state = visibility; if (visibility == SymbolState::kPublic) { - // This is a public symbol, we must encode the ID now if there is - // one. + // This is a public symbol, we must encode the ID now if there is one. if (pbEntry.has_id()) { entry->id = static_cast<uint16_t>(pbEntry.id()); } @@ -142,16 +138,15 @@ class PackagePbDeserializer { return {}; } - ResourceConfigValue* configValue = - entry->FindOrCreateValue(config, pbConfig.product()); + ResourceConfigValue* configValue = entry->FindOrCreateValue(config, pbConfig.product()); if (configValue->value) { // Duplicate config. diag_->Error(DiagMessage(source_) << "duplicate configuration"); return {}; } - configValue->value = DeserializeValueFromPb( - pbConfigValue.value(), config, &table->string_pool); + configValue->value = + DeserializeValueFromPb(pbConfigValue.value(), config, &table->string_pool); if (!configValue->value) { return {}; } diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp index 7230b55e10e3..de10bb80bf7e 100644 --- a/tools/aapt2/proto/TableProtoSerializer.cpp +++ b/tools/aapt2/proto/TableProtoSerializer.cpp @@ -250,19 +250,16 @@ std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table) { // Write the SymbolStatus struct. pb::SymbolStatus* pb_status = pb_entry->mutable_symbol_status(); - pb_status->set_visibility( - SerializeVisibilityToPb(entry->symbol_status.state)); - SerializeSourceToPb(entry->symbol_status.source, &source_pool, - pb_status->mutable_source()); + pb_status->set_visibility(SerializeVisibilityToPb(entry->symbol_status.state)); + SerializeSourceToPb(entry->symbol_status.source, &source_pool, pb_status->mutable_source()); pb_status->set_comment(entry->symbol_status.comment); + pb_status->set_allow_new(entry->symbol_status.allow_new); for (auto& config_value : entry->values) { pb::ConfigValue* pb_config_value = pb_entry->add_config_values(); - SerializeConfig(config_value->config, - pb_config_value->mutable_config()); + SerializeConfig(config_value->config, pb_config_value->mutable_config()); if (!config_value->product.empty()) { - pb_config_value->mutable_config()->set_product( - config_value->product); + pb_config_value->mutable_config()->set_product(config_value->product); } pb::Value* pb_value = pb_config_value->mutable_value(); diff --git a/tools/aapt2/proto/TableProtoSerializer_test.cpp b/tools/aapt2/proto/TableProtoSerializer_test.cpp index fdd5197167ef..e6ce6d37b879 100644 --- a/tools/aapt2/proto/TableProtoSerializer_test.cpp +++ b/tools/aapt2/proto/TableProtoSerializer_test.cpp @@ -28,12 +28,11 @@ TEST(TableProtoSerializer, SerializeSinglePackage) { std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) - .AddFileReference("com.app.a:layout/main", ResourceId(0x7f020000), - "res/layout/main.xml") - .AddReference("com.app.a:layout/other", ResourceId(0x7f020001), - "com.app.a:layout/main") + .AddFileReference("com.app.a:layout/main", ResourceId(0x7f020000), "res/layout/main.xml") + .AddReference("com.app.a:layout/other", ResourceId(0x7f020001), "com.app.a:layout/main") .AddString("com.app.a:string/text", {}, "hi") .AddValue("com.app.a:id/foo", {}, util::make_unique<Id>()) + .SetSymbolState("com.app.a:bool/foo", {}, SymbolState::kUndefined, true /*allow_new*/) .Build(); Symbol public_symbol; @@ -94,21 +93,23 @@ TEST(TableProtoSerializer, SerializeSinglePackage) { EXPECT_EQ(SymbolState::kPublic, result.value().type->symbol_status.state); EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbol_status.state); + result = new_table->FindResource(test::ParseNameOrDie("com.app.a:bool/foo")); + ASSERT_TRUE(result); + EXPECT_EQ(SymbolState::kUndefined, result.value().entry->symbol_status.state); + EXPECT_TRUE(result.value().entry->symbol_status.allow_new); + // Find the product-dependent values BinaryPrimitive* prim = test::GetValueForConfigAndProduct<BinaryPrimitive>( - new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), - ""); + new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), ""); ASSERT_NE(nullptr, prim); EXPECT_EQ(123u, prim->value.data); prim = test::GetValueForConfigAndProduct<BinaryPrimitive>( - new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), - "tablet"); + new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), "tablet"); ASSERT_NE(nullptr, prim); EXPECT_EQ(321u, prim->value.data); - Reference* actual_ref = - test::GetValue<Reference>(new_table.get(), "com.app.a:layout/abc"); + Reference* actual_ref = test::GetValue<Reference>(new_table.get(), "com.app.a:layout/abc"); ASSERT_NE(nullptr, actual_ref); AAPT_ASSERT_TRUE(actual_ref->name); AAPT_ASSERT_TRUE(actual_ref->id); diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md index ac09b5933ef6..0290e30dfced 100644 --- a/tools/aapt2/readme.md +++ b/tools/aapt2/readme.md @@ -3,6 +3,7 @@ ## Version 2.17 ### `aapt2 compile ...` - Fixed an issue where symlinks would not be followed when compiling PNGs. (bug 62144459) +- Fixed issue where overlays that declared `<add-resource>` did not compile. (bug 38355988) ## Version 2.16 ### `aapt2 link ...` diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h index 6888cf32fab8..02acedbd8ac5 100644 --- a/tools/aapt2/test/Builders.h +++ b/tools/aapt2/test/Builders.h @@ -117,12 +117,12 @@ class ResourceTableBuilder { } ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id, - SymbolState state) { + SymbolState state, bool allow_new = false) { ResourceName res_name = ParseNameOrDie(name); Symbol symbol; symbol.state = state; - CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, - &diagnostics_)); + symbol.allow_new = allow_new; + CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, &diagnostics_)); return *this; } diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h index 248921f3afea..a937de8869a6 100644 --- a/tools/aapt2/test/Common.h +++ b/tools/aapt2/test/Common.h @@ -22,12 +22,14 @@ #include "android-base/logging.h" #include "android-base/macros.h" #include "androidfw/StringPiece.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" #include "ConfigDescription.h" #include "Debug.h" #include "ResourceTable.h" #include "ResourceUtils.h" +#include "ResourceValues.h" #include "ValueVisitor.h" #include "io/File.h" #include "process/IResourceTableConsumer.h" @@ -51,13 +53,11 @@ struct DummyDiagnosticsImpl : public IDiagnostics { return; case Level::Warn: - std::cerr << actual_msg.source << ": warn: " << actual_msg.message - << "." << std::endl; + std::cerr << actual_msg.source << ": warn: " << actual_msg.message << "." << std::endl; break; case Level::Error: - std::cerr << actual_msg.source << ": error: " << actual_msg.message - << "." << std::endl; + std::cerr << actual_msg.source << ": error: " << actual_msg.message << "." << std::endl; break; } } @@ -84,11 +84,9 @@ template <typename T> T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece& res_name, const ConfigDescription& config, const android::StringPiece& product) { - Maybe<ResourceTable::SearchResult> result = - table->FindResource(ParseNameOrDie(res_name)); + Maybe<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name)); if (result) { - ResourceConfigValue* config_value = - result.value().entry->FindValue(config, product); + ResourceConfigValue* config_value = result.value().entry->FindValue(config, product); if (config_value) { return ValueCast<T>(config_value->value.get()); } @@ -111,9 +109,13 @@ class TestFile : public io::IFile { public: explicit TestFile(const android::StringPiece& path) : source_(path) {} - std::unique_ptr<io::IData> OpenAsData() override { return {}; } + std::unique_ptr<io::IData> OpenAsData() override { + return {}; + } - const Source& GetSource() const override { return source_; } + const Source& GetSource() const override { + return source_; + } private: DISALLOW_COPY_AND_ASSIGN(TestFile); @@ -122,6 +124,47 @@ class TestFile : public io::IFile { }; } // namespace test + +// Workaround gtest bug (https://github.com/google/googletest/issues/443) +// that does not select base class operator<< for derived class T. +template <typename T> +typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type operator<<( + std::ostream& out, const T& value) { + value.Print(&out); + return out; +} + +template std::ostream& operator<<<Item>(std::ostream&, const Item&); +template std::ostream& operator<<<Reference>(std::ostream&, const Reference&); +template std::ostream& operator<<<Id>(std::ostream&, const Id&); +template std::ostream& operator<<<RawString>(std::ostream&, const RawString&); +template std::ostream& operator<<<String>(std::ostream&, const String&); +template std::ostream& operator<<<StyledString>(std::ostream&, const StyledString&); +template std::ostream& operator<<<FileReference>(std::ostream&, const FileReference&); +template std::ostream& operator<<<BinaryPrimitive>(std::ostream&, const BinaryPrimitive&); +template std::ostream& operator<<<Attribute>(std::ostream&, const Attribute&); +template std::ostream& operator<<<Style>(std::ostream&, const Style&); +template std::ostream& operator<<<Array>(std::ostream&, const Array&); +template std::ostream& operator<<<Plural>(std::ostream&, const Plural&); + +// Add a print method to Maybe. +template <typename T> +void PrintTo(const Maybe<T>& value, std::ostream* out) { + if (value) { + *out << ::testing::PrintToString(value.value()); + } else { + *out << "Nothing"; + } +} + +namespace test { + +MATCHER_P(ValueEq, a, + std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) { + return arg.Equals(&a); +} + +} // namespace test } // namespace aapt #endif /* AAPT_TEST_COMMON_H */ diff --git a/tools/aapt2/test/Test.h b/tools/aapt2/test/Test.h index ec07432fa51e..a24c01cd4137 100644 --- a/tools/aapt2/test/Test.h +++ b/tools/aapt2/test/Test.h @@ -17,6 +17,7 @@ #ifndef AAPT_TEST_TEST_H #define AAPT_TEST_TEST_H +#include "gmock/gmock.h" #include "gtest/gtest.h" #include "test/Builders.h" diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 15fd2ceea5fa..deb0e09e6f72 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -18,6 +18,7 @@ package android.view; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.GraphicBuffer; import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; @@ -210,13 +211,13 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, + public void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp) throws RemoteException { // TODO Auto-generated method stub } @Override - public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, + public void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) { // TODO Auto-generated method stub diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index cfc1fd252fb3..58df4ee227f2 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -160,6 +160,8 @@ public class WifiManager { * * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered * components will be launched. + * + * @hide */ public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; /** @@ -167,6 +169,8 @@ public class WifiManager { * String representation. * * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}. + * + * @hide */ public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; /** @@ -174,12 +178,16 @@ public class WifiManager { * * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into * {@link android.graphics.drawable.Icon}. + * + * @hide */ public static final String EXTRA_ICON = "android.net.wifi.extra.ICON"; /** * Name of a file. * * Retrieve with {@link android.content.Intent#getStringExtra(String)}. + * + * @hide */ public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; @@ -195,6 +203,7 @@ public class WifiManager { * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered * components will be launched. * + * @hide */ public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; @@ -202,6 +211,8 @@ public class WifiManager { * Raw binary data of an ANQP (Access Network Query Protocol) element. * * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}. + * + * @hide */ public static final String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA"; @@ -220,6 +231,7 @@ public class WifiManager { * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered * components will be launched. * + * @hide */ public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; @@ -228,18 +240,24 @@ public class WifiManager { * {@code true} for ESS. * * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}. + * + * @hide */ public static final String EXTRA_ESS = "android.net.wifi.extra.ESS"; /** * Delay in seconds. * * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. + * + * @hide */ public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; /** * String representation of an URL. * * Retrieve with {@link android.content.Intent#getStringExtra(String)}. + * + * @hide */ public static final String EXTRA_URL = "android.net.wifi.extra.URL"; @@ -254,8 +272,10 @@ public class WifiManager { * * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE * - ** <p>Note: The broadcast is only delivered to registered receivers - no manifest registered + * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered * components will be launched. + * + * @hide */ public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; @@ -265,6 +285,8 @@ public class WifiManager { * 1 - SOAP XML SPP * * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. + * + * @hide */ public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; @@ -1058,11 +1080,9 @@ public class WifiManager { * Name). In the case when there is an existing configuration with the same * FQDN, the new configuration will replace the existing configuration. * - * An {@link IllegalArgumentException} will be thrown on failure. - * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled - * on the device. - * * @param config The Passpoint configuration to be added + * @throws IllegalArgumentException if configuration is invalid + * @throws UnsupportedOperationException if Passpoint is not enabled on the device. */ public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) { try { @@ -1077,11 +1097,9 @@ public class WifiManager { /** * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). * - * An {@link IllegalArgumentException} will be thrown on failure. - * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled - * on the device. - * * @param fqdn The FQDN of the Passpoint configuration to be removed + * @throws IllegalArgumentException if no configuration is associated with the given FQDN. + * @throws UnsupportedOperationException if Passpoint is not enabled on the device. */ public void removePasspointConfiguration(String fqdn) { try { @@ -1098,10 +1116,8 @@ public class WifiManager { * * An empty list will be returned when no configurations are installed. * - * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled - * on the device. - * * @return A list of {@link PasspointConfiguration} + * @throws UnsupportedOperationException if Passpoint is not enabled on the device. */ public List<PasspointConfiguration> getPasspointConfigurations() { try { @@ -1117,11 +1133,11 @@ public class WifiManager { * {@link #EXTRA_ICON} will indicate the result of the request. * A missing intent extra {@link #EXTRA_ICON} will indicate a failure. * - * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled - * on the device. - * * @param bssid The BSSID of the AP * @param fileName Name of the icon file (remote file) to query from the AP + * + * @throws UnsupportedOperationException if Passpoint is not enabled on the device. + * @hide */ public void queryPasspointIcon(long bssid, String fileName) { try { @@ -1778,25 +1794,25 @@ public class WifiManager { } /** - * Start AccessPoint mode with the specified - * configuration. If the radio is already running in - * AP mode, update the new configuration - * Note that starting in access point mode disables station - * mode operation + * This call will be deprecated and removed in an upcoming release. It is no longer used to + * start WiFi Tethering. Please use {@link ConnectivityManager#startTethering(int, boolean, + * ConnectivityManager#OnStartTetheringCallback)} if + * the caller has proper permissions. Callers can also use the LocalOnlyHotspot feature for a + * hotspot capable of communicating with co-located devices {@link + * WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)}. + * * @param wifiConfig SSID, security and channel details as * part of WifiConfiguration - * @return {@code true} if the operation succeeds, {@code false} otherwise + * @return {@code false} * * @hide */ @SystemApi public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { - try { - mService.setWifiApEnabled(wifiConfig, enabled); - return true; - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + String packageName = mContext.getOpPackageName(); + + Log.w(TAG, packageName + " attempted call to setWifiApEnabled: enabled = " + enabled); + return false; } /** diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java index f892bb0a3884..71d4173a389c 100644 --- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java @@ -62,16 +62,36 @@ public final class PasspointConfiguration implements Parcelable { * Configurations under HomeSp subtree. */ private HomeSp mHomeSp = null; + /** + * Set the Home SP (Service Provider) information. + * + * @param homeSp The Home SP information to set to + */ public void setHomeSp(HomeSp homeSp) { mHomeSp = homeSp; } + /** + * Get the Home SP (Service Provider) information. + * + * @return Home SP information + */ public HomeSp getHomeSp() { return mHomeSp; } /** * Configurations under Credential subtree. */ private Credential mCredential = null; + /** + * Set the credential information. + * + * @param credential The credential information to set to + */ public void setCredential(Credential credential) { mCredential = credential; } + /** + * Get the credential information. + * + * @return credential information + */ public Credential getCredential() { return mCredential; } diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java index d712feb7c6d2..e8fcbfd6731e 100644 --- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java +++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java @@ -97,9 +97,19 @@ public final class Credential implements Parcelable { * comparing the realm specified in that hotspot's ANQP element. */ private String mRealm = null; + /** + * Set the realm associated with this credential. + * + * @param realm The realm to set to + */ public void setRealm(String realm) { mRealm = realm; } + /** + * Get the realm associated with this credential. + * + * @return the realm associated with this credential + */ public String getRealm() { return mRealm; } @@ -162,9 +172,19 @@ public final class Credential implements Parcelable { * Username of the credential. */ private String mUsername = null; + /** + * Set the username associated with this user credential. + * + * @param username The username to set to + */ public void setUsername(String username) { mUsername = username; } + /** + * Get the username associated with this user credential. + * + * @return the username associated with this user credential + */ public String getUsername() { return mUsername; } @@ -173,9 +193,19 @@ public final class Credential implements Parcelable { * Base64-encoded password. */ private String mPassword = null; + /** + * Set the Base64-encoded password associated with this user credential. + * + * @param password The password to set to + */ public void setPassword(String password) { mPassword = password; } + /** + * Get the Base64-encoded password associated with this user credential. + * + * @return the Base64-encoded password associated with this user credential + */ public String getPassword() { return mPassword; } @@ -233,14 +263,30 @@ public final class Credential implements Parcelable { /** * EAP (Extensible Authentication Protocol) method type. - * Refer to http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4 - * for valid values. + * Refer to + * <a href="http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4"> + * EAP Numbers</a> for valid values. * Using Integer.MIN_VALUE to indicate unset value. */ private int mEapType = Integer.MIN_VALUE; + /** + * Set the EAP (Extensible Authentication Protocol) method type associated with this + * user credential. + * Refer to + * <a href="http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4"> + * EAP Numbers</a> for valid values. + * + * @param eapType The EAP method type associated with this user credential + */ public void setEapType(int eapType) { mEapType = eapType; } + /** + * Get the EAP (Extensible Authentication Protocol) method type associated with this + * user credential. + * + * @return EAP method type + */ public int getEapType() { return mEapType; } @@ -249,9 +295,19 @@ public final class Credential implements Parcelable { * Non-EAP inner authentication method. */ private String mNonEapInnerMethod = null; + /** + * Set the inner non-EAP method associated with this user credential. + * + * @param nonEapInnerMethod The non-EAP inner method to set to + */ public void setNonEapInnerMethod(String nonEapInnerMethod) { mNonEapInnerMethod = nonEapInnerMethod; } + /** + * Get the inner non-EAP method associated with this user credential. + * + * @return Non-EAP inner method associated with this user credential + */ public String getNonEapInnerMethod() { return mNonEapInnerMethod; } @@ -394,9 +450,19 @@ public final class Credential implements Parcelable { }; } private UserCredential mUserCredential = null; + /** + * Set the user credential information. + * + * @param userCredential The user credential to set to + */ public void setUserCredential(UserCredential userCredential) { mUserCredential = userCredential; } + /** + * Get the user credential information. + * + * @return user credential information + */ public UserCredential getUserCredential() { return mUserCredential; } @@ -421,9 +487,19 @@ public final class Credential implements Parcelable { * Certificate type. */ private String mCertType = null; + /** + * Set the certificate type associated with this certificate credential. + * + * @param certType The certificate type to set to + */ public void setCertType(String certType) { mCertType = certType; } + /** + * Get the certificate type associated with this certificate credential. + * + * @return certificate type + */ public String getCertType() { return mCertType; } @@ -432,9 +508,19 @@ public final class Credential implements Parcelable { * The SHA-256 fingerprint of the certificate. */ private byte[] mCertSha256Fingerprint = null; + /** + * Set the certificate SHA-256 fingerprint associated with this certificate credential. + * + * @param certSha256Fingerprint The certificate fingerprint to set to + */ public void setCertSha256Fingerprint(byte[] certSha256Fingerprint) { mCertSha256Fingerprint = certSha256Fingerprint; } + /** + * Get the certificate SHA-256 fingerprint associated with this certificate credential. + * + * @return certificate SHA-256 fingerprint + */ public byte[] getCertSha256Fingerprint() { return mCertSha256Fingerprint; } @@ -530,9 +616,19 @@ public final class Credential implements Parcelable { }; } private CertificateCredential mCertCredential = null; + /** + * Set the certificate credential information. + * + * @param certCredential The certificate credential to set to + */ public void setCertCredential(CertificateCredential certCredential) { mCertCredential = certCredential; } + /** + * Get the certificate credential information. + * + * @return certificate credential information + */ public CertificateCredential getCertCredential() { return mCertCredential; } @@ -553,9 +649,21 @@ public final class Credential implements Parcelable { * cellular networks */ private String mImsi = null; + /** + * Set the IMSI (International Mobile Subscriber Identity) associated with this SIM + * credential. + * + * @param imsi The IMSI to set to + */ public void setImsi(String imsi) { mImsi = imsi; } + /** + * Get the IMSI (International Mobile Subscriber Identity) associated with this SIM + * credential. + * + * @return IMSI associated with this SIM credential + */ public String getImsi() { return mImsi; } @@ -567,9 +675,21 @@ public final class Credential implements Parcelable { * Using Integer.MIN_VALUE to indicate unset value. */ private int mEapType = Integer.MIN_VALUE; + /** + * Set the EAP (Extensible Authentication Protocol) method type associated with this + * SIM credential. + * + * @param eapType The EAP method type to set to + */ public void setEapType(int eapType) { mEapType = eapType; } + /** + * Get the EAP (Extensible Authentication Protocol) method type associated with this + * SIM credential. + * + * @return EAP method type associated with this SIM credential + */ public int getEapType() { return mEapType; } @@ -704,9 +824,19 @@ public final class Credential implements Parcelable { } } private SimCredential mSimCredential = null; + /** + * Set the SIM credential information. + * + * @param simCredential The SIM credential to set to + */ public void setSimCredential(SimCredential simCredential) { mSimCredential = simCredential; } + /** + * Get the SIM credential information. + * + * @return SIM credential information + */ public SimCredential getSimCredential() { return mSimCredential; } @@ -715,9 +845,19 @@ public final class Credential implements Parcelable { * CA (Certificate Authority) X509 certificate. */ private X509Certificate mCaCertificate = null; + /** + * Set the CA (Certification Authority) certificate associated with this credential. + * + * @param caCertificate The CA certificate to set to + */ public void setCaCertificate(X509Certificate caCertificate) { mCaCertificate = caCertificate; } + /** + * Get the CA (Certification Authority) certificate associated with this credential. + * + * @return CA certificate associated with this credential + */ public X509Certificate getCaCertificate() { return mCaCertificate; } @@ -726,9 +866,19 @@ public final class Credential implements Parcelable { * Client side X509 certificate chain. */ private X509Certificate[] mClientCertificateChain = null; + /** + * Set the client certificate chain associated with this credential. + * + * @param certificateChain The client certificate chain to set to + */ public void setClientCertificateChain(X509Certificate[] certificateChain) { mClientCertificateChain = certificateChain; } + /** + * Get the client certificate chain associated with this credential. + * + * @return client certificate chain associated with this credential + */ public X509Certificate[] getClientCertificateChain() { return mClientCertificateChain; } @@ -737,9 +887,19 @@ public final class Credential implements Parcelable { * Client side private key. */ private PrivateKey mClientPrivateKey = null; + /** + * Set the client private key associated with this credential. + * + * @param clientPrivateKey the client private key to set to + */ public void setClientPrivateKey(PrivateKey clientPrivateKey) { mClientPrivateKey = clientPrivateKey; } + /** + * Get the client private key associated with this credential. + * + * @return client private key associated with this credential. + */ public PrivateKey getClientPrivateKey() { return mClientPrivateKey; } diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java index 2247860d23a5..d829ea81ed56 100644 --- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java +++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java @@ -52,9 +52,19 @@ public final class HomeSp implements Parcelable { * FQDN (Fully Qualified Domain Name) of this home service provider. */ private String mFqdn = null; + /** + * Set the FQDN (Fully Qualified Domain Name) associated with this home service provider. + * + * @param fqdn The FQDN to set to + */ public void setFqdn(String fqdn) { mFqdn = fqdn; } + /** + * Get the FQDN (Fully Qualified Domain Name) associated with this home service provider. + * + * @return the FQDN associated with this home service provider + */ public String getFqdn() { return mFqdn; } @@ -63,9 +73,19 @@ public final class HomeSp implements Parcelable { * Friendly name of this home service provider. */ private String mFriendlyName = null; + /** + * Set the friendly name associated with this home service provider. + * + * @param friendlyName The friendly name to set to + */ public void setFriendlyName(String friendlyName) { mFriendlyName = friendlyName; } + /** + * Get the friendly name associated with this home service provider. + * + * @return the friendly name associated with this home service provider + */ public String getFriendlyName() { return mFriendlyName; } @@ -184,9 +204,21 @@ public final class HomeSp implements Parcelable { * which this provider is a member. */ private long[] mRoamingConsortiumOis = null; + /** + * Set the Organization Identifiers (OIs) identifying a roaming consortium of which this + * provider is a member. + * + * @param roamingConsortiumOis Array of roaming consortium OIs + */ public void setRoamingConsortiumOis(long[] roamingConsortiumOis) { mRoamingConsortiumOis = roamingConsortiumOis; } + /** + * Get the Organization Identifiers (OIs) identifying a roaming consortium of which this + * provider is a member. + * + * @return array of roaming consortium OIs + */ public long[] getRoamingConsortiumOis() { return mRoamingConsortiumOis; } diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index 84ac1183c897..b235ccc7a89e 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -778,4 +778,13 @@ public class WifiManagerTest { verify(mWifiService).stopWatchLocalOnlyHotspot(); } + /** + * Verify that calls to setWifiApEnabled return false. + */ + @Test + public void testSetWifiApEnabledReturnsFalse() throws Exception { + assertFalse(mWifiManager.setWifiApEnabled(null, true)); + assertFalse(mWifiManager.setWifiApEnabled(null, false)); + verify(mWifiService, never()).setWifiApEnabled(any(), anyBoolean()); + } } |