Merge changes from topic "large-icons-tm" into tm-dev
* changes:
Size restrict right notification icon size
Downscale large bitmaps in CachingIconView
Support downscaling of Drawable icons in LocalImageResolver
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
index 4ad015d..c92c634 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java
@@ -20,6 +20,7 @@
import android.app.Activity;
import android.content.Context;
+import android.os.Bundle;
import android.os.RemoteException;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
@@ -153,7 +154,8 @@
while (state.keepRunning()) {
session.relayout(mWindow, mParams, mWidth, mHeight,
mViewVisibility.getAsInt(), mFlags, mOutFrames,
- mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls);
+ mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls,
+ new Bundle());
}
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 90ec700..528be3c 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -4891,13 +4891,15 @@
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
filter.addDataScheme(IntentFilter.SCHEME_PACKAGE);
- getContext().registerReceiver(this, filter);
+ getContext().registerReceiverForAllUsers(this, filter,
+ /* broadcastPermission */ null, /* scheduler */ null);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
sdFilter.addAction(Intent.ACTION_USER_STOPPED);
sdFilter.addAction(Intent.ACTION_UID_REMOVED);
- getContext().registerReceiver(this, sdFilter);
+ getContext().registerReceiverForAllUsers(this, sdFilter,
+ /* broadcastPermission */ null, /* scheduler */ null);
}
@Override
@@ -4915,9 +4917,6 @@
}
}
return;
- case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
- pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- break;
case Intent.ACTION_USER_STOPPED:
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userHandle >= 0) {
@@ -4932,6 +4931,18 @@
mRemovalHistory.delete(uid);
mLastOpScheduleExactAlarm.delete(uid);
return;
+ case Intent.ACTION_PACKAGE_ADDED:
+ if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ final String packageUpdated = intent.getData().getSchemeSpecificPart();
+ mHandler.obtainMessage(
+ AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE, uid, -1,
+ packageUpdated).sendToTarget();
+ }
+ mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
+ return;
+ case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ break;
case Intent.ACTION_PACKAGE_REMOVED:
if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
// This package is being updated; don't kill its alarms.
@@ -4950,15 +4961,6 @@
}
}
break;
- case Intent.ACTION_PACKAGE_ADDED:
- if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
- final String packageUpdated = intent.getData().getSchemeSpecificPart();
- mHandler.obtainMessage(
- AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE, uid, -1,
- packageUpdated).sendToTarget();
- }
- mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
- return;
}
if (pkgList != null && (pkgList.length > 0)) {
for (String pkg : pkgList) {
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index 6a685a79..a157517 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -64,8 +64,6 @@
"libwilhelm",
],
- header_libs: ["bionic_libc_platform_headers"],
-
compile_multilib: "both",
cflags: [
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 815f945..12083b6 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -15,7 +15,6 @@
#include <android-base/macros.h>
#include <binder/IPCThreadState.h>
-#include <bionic/pac.h>
#include <hwbinder/IPCThreadState.h>
#include <utils/Log.h>
#include <cutils/memory.h>
@@ -183,10 +182,6 @@
ALOGV("app_process main with argv: %s", argv_String.string());
}
- // Because of applications that are using PAC instructions incorrectly, PAC
- // is disabled in application processes for now.
- ScopedDisablePAC x;
-
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index c202f6f..6ef6845 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -52,6 +52,7 @@
"-readability-braces-around-statements",
"-readability-const-return-type",
"-readability-convert-member-functions-to-static",
+ "-readability-duplicate-include",
"-readability-else-after-return",
"-readability-identifier-length",
"-readability-named-parameter",
diff --git a/core/api/current.txt b/core/api/current.txt
index 19ffd36e..45f7cf2 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -3901,7 +3901,7 @@
method public Object getAnimatedValue(String);
method public long getCurrentPlayTime();
method public long getDuration();
- method @FloatRange(from=0, to=1) public static float getDurationScale();
+ method @FloatRange(from=0) public static float getDurationScale();
method public static long getFrameDelay();
method public int getRepeatCount();
method public int getRepeatMode();
@@ -3941,7 +3941,7 @@
}
public static interface ValueAnimator.DurationScaleChangeListener {
- method public void onChanged(float);
+ method public void onChanged(@FloatRange(from=0) float);
}
}
@@ -16407,12 +16407,8 @@
package android.graphics.text {
public final class LineBreakConfig {
- ctor public LineBreakConfig();
method public int getLineBreakStyle();
method public int getLineBreakWordStyle();
- method public void set(@NonNull android.graphics.text.LineBreakConfig);
- method public void setLineBreakStyle(int);
- method public void setLineBreakWordStyle(int);
field public static final int LINE_BREAK_STYLE_LOOSE = 1; // 0x1
field public static final int LINE_BREAK_STYLE_NONE = 0; // 0x0
field public static final int LINE_BREAK_STYLE_NORMAL = 2; // 0x2
@@ -16421,6 +16417,13 @@
field public static final int LINE_BREAK_WORD_STYLE_PHRASE = 1; // 0x1
}
+ public static final class LineBreakConfig.Builder {
+ ctor public LineBreakConfig.Builder();
+ method @NonNull public android.graphics.text.LineBreakConfig build();
+ method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakStyle(int);
+ method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakWordStyle(int);
+ }
+
public class LineBreaker {
method @NonNull public android.graphics.text.LineBreaker.Result computeLineBreaks(@NonNull android.graphics.text.MeasuredText, @NonNull android.graphics.text.LineBreaker.ParagraphConstraints, @IntRange(from=0) int);
field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
@@ -17408,7 +17411,7 @@
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Long> REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_ROTATE_AND_CROP_MODES;
- field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_STREAM_USE_CASES;
+ field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<long[]> SCALER_AVAILABLE_STREAM_USE_CASES;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SCALER_CROPPING_TYPE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Size> SCALER_DEFAULT_SECURE_IMAGE_SIZE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS;
@@ -18193,7 +18196,7 @@
method public int get10BitFormat();
method @NonNull public java.util.List<android.util.Size> getAvailableSizes();
method public int getFormat();
- method public int getStreamUseCase();
+ method public long getStreamUseCase();
method public boolean is10BitCapable();
method public boolean isInput();
method public boolean isMaximumSize();
@@ -18251,7 +18254,7 @@
method public long getDynamicRangeProfile();
method public int getMaxSharedSurfaceCount();
method public int getMirrorMode();
- method public int getStreamUseCase();
+ method public long getStreamUseCase();
method @Nullable public android.view.Surface getSurface();
method public int getSurfaceGroupId();
method @NonNull public java.util.List<android.view.Surface> getSurfaces();
@@ -18261,7 +18264,7 @@
method public void setDynamicRangeProfile(long);
method public void setMirrorMode(int);
method public void setPhysicalCameraId(@Nullable String);
- method public void setStreamUseCase(int);
+ method public void setStreamUseCase(long);
method public void setTimestampBase(int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.camera2.params.OutputConfiguration> CREATOR;
@@ -45062,7 +45065,7 @@
public static final class PrecomputedText.Params {
method public int getBreakStrategy();
method public int getHyphenationFrequency();
- method @Nullable public android.graphics.text.LineBreakConfig getLineBreakConfig();
+ method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
method @NonNull public android.text.TextDirectionHeuristic getTextDirection();
method @NonNull public android.text.TextPaint getTextPaint();
}
@@ -57352,7 +57355,8 @@
method public final android.text.Layout getLayout();
method public float getLetterSpacing();
method public int getLineBounds(int, android.graphics.Rect);
- method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
+ method public int getLineBreakStyle();
+ method public int getLineBreakWordStyle();
method public int getLineCount();
method public int getLineHeight();
method public float getLineSpacingExtra();
@@ -57480,7 +57484,8 @@
method public void setKeyListener(android.text.method.KeyListener);
method public void setLastBaselineToBottomHeight(@IntRange(from=0) @Px int);
method public void setLetterSpacing(float);
- method public void setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig);
+ method public void setLineBreakStyle(int);
+ method public void setLineBreakWordStyle(int);
method public void setLineHeight(@IntRange(from=0) @Px int);
method public void setLineSpacing(float, float);
method public void setLines(int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 09d1114..2e73ef3 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -9791,6 +9791,7 @@
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isManagedProfile(int);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isMediaSharedWithParent();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
+ method public static boolean isRemoveResultSuccessful(int);
method public boolean isRestrictedProfile();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
@@ -9808,7 +9809,10 @@
field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
field public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2; // 0x2
field public static final int REMOVE_RESULT_DEFERRED = 1; // 0x1
- field public static final int REMOVE_RESULT_ERROR = 3; // 0x3
+ field public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4; // 0xfffffffc
+ field public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
+ field public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3; // 0xfffffffd
+ field public static final int REMOVE_RESULT_ERROR_USER_RESTRICTION = -2; // 0xfffffffe
field public static final int REMOVE_RESULT_REMOVED = 0; // 0x0
field public static final int RESTRICTION_NOT_SET = 0; // 0x0
field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 66f893d..db95a1f 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -96,7 +96,7 @@
package android.animation {
public class ValueAnimator extends android.animation.Animator {
- method @MainThread public static void setDurationScale(@FloatRange(from=0, to=1) float);
+ method @MainThread public static void setDurationScale(@FloatRange(from=0) float);
}
}
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index bca6b6a..6ab7ae6 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -316,7 +316,7 @@
@UnsupportedAppUsage
@TestApi
@MainThread
- public static void setDurationScale(@FloatRange(from = 0, to = 1) float durationScale) {
+ public static void setDurationScale(@FloatRange(from = 0) float durationScale) {
sDurationScale = durationScale;
List<WeakReference<DurationScaleChangeListener>> listenerCopy;
@@ -340,7 +340,7 @@
*
* @return the duration scale.
*/
- @FloatRange(from = 0, to = 1)
+ @FloatRange(from = 0)
public static float getDurationScale() {
return sDurationScale;
}
@@ -1798,8 +1798,8 @@
public interface DurationScaleChangeListener {
/**
* Called when the duration scale changes.
- * @param scale the duration scalel
+ * @param scale the duration scale
*/
- void onChanged(float scale);
+ void onChanged(@FloatRange(from = 0) float scale);
}
}
diff --git a/core/java/android/hardware/CameraStreamStats.java b/core/java/android/hardware/CameraStreamStats.java
index 7b24cc4..3952467 100644
--- a/core/java/android/hardware/CameraStreamStats.java
+++ b/core/java/android/hardware/CameraStreamStats.java
@@ -49,7 +49,7 @@
private float[] mHistogramBins;
private long[] mHistogramCounts;
private long mDynamicRangeProfile;
- private int mStreamUseCase;
+ private long mStreamUseCase;
private static final String TAG = "CameraStreamStats";
@@ -73,7 +73,7 @@
public CameraStreamStats(int width, int height, int format, float maxPreviewFps,
int dataSpace, long usage, long requestCount, long errorCount,
int startLatencyMs, int maxHalBuffers, int maxAppBuffers, long dynamicRangeProfile,
- int streamUseCase) {
+ long streamUseCase) {
mWidth = width;
mHeight = height;
mFormat = format;
@@ -135,7 +135,7 @@
dest.writeFloatArray(mHistogramBins);
dest.writeLongArray(mHistogramCounts);
dest.writeLong(mDynamicRangeProfile);
- dest.writeInt(mStreamUseCase);
+ dest.writeLong(mStreamUseCase);
}
public void readFromParcel(Parcel in) {
@@ -154,7 +154,7 @@
mHistogramBins = in.createFloatArray();
mHistogramCounts = in.createLongArray();
mDynamicRangeProfile = in.readLong();
- mStreamUseCase = in.readInt();
+ mStreamUseCase = in.readLong();
}
public int getWidth() {
@@ -217,7 +217,7 @@
return mDynamicRangeProfile;
}
- public int getStreamUseCase() {
+ public long getStreamUseCase() {
return mStreamUseCase;
}
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 7bebe1f..b05e6d1 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -3563,8 +3563,8 @@
*/
@PublicKey
@NonNull
- public static final Key<int[]> SCALER_AVAILABLE_STREAM_USE_CASES =
- new Key<int[]>("android.scaler.availableStreamUseCases", int[].class);
+ public static final Key<long[]> SCALER_AVAILABLE_STREAM_USE_CASES =
+ new Key<long[]>("android.scaler.availableStreamUseCases", long[].class);
/**
* <p>An array of mandatory stream combinations with stream use cases.
diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
index 465abfb..a3bc665 100644
--- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
+++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
@@ -66,7 +66,7 @@
private final boolean mIsUltraHighResolution;
private final boolean mIsMaximumSize;
private final boolean mIs10BitCapable;
- private final int mStreamUseCase;
+ private final long mStreamUseCase;
/**
* Create a new {@link MandatoryStreamInformation}.
@@ -168,7 +168,7 @@
*/
public MandatoryStreamInformation(@NonNull List<Size> availableSizes, @Format int format,
boolean isMaximumSize, boolean isInput, boolean isUltraHighResolution,
- boolean is10BitCapable, @StreamUseCase int streamUseCase) {
+ boolean is10BitCapable, @StreamUseCase long streamUseCase) {
if (availableSizes.isEmpty()) {
throw new IllegalArgumentException("No available sizes");
}
@@ -308,9 +308,9 @@
* For {@link MandatoryStreamInformation} belonging to other mandatory stream
* combinations, the return value will be DEFAULT. </p>
*
- * @return the integer stream use case.
+ * @return the long integer stream use case.
*/
- public @StreamUseCase int getStreamUseCase() {
+ public @StreamUseCase long getStreamUseCase() {
return mStreamUseCase;
}
@@ -365,15 +365,15 @@
/**
* Short hand for stream use cases
*/
- private static final int STREAM_USE_CASE_PREVIEW =
+ private static final long STREAM_USE_CASE_PREVIEW =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW;
- private static final int STREAM_USE_CASE_STILL_CAPTURE =
+ private static final long STREAM_USE_CASE_STILL_CAPTURE =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE;
- private static final int STREAM_USE_CASE_RECORD =
+ private static final long STREAM_USE_CASE_RECORD =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD;
- private static final int STREAM_USE_CASE_PREVIEW_VIDEO_STILL =
+ private static final long STREAM_USE_CASE_PREVIEW_VIDEO_STILL =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL;
- private static final int STREAM_USE_CASE_VIDEO_CALL =
+ private static final long STREAM_USE_CASE_VIDEO_CALL =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
/**
@@ -471,12 +471,12 @@
private static final class StreamTemplate {
public int mFormat;
public SizeThreshold mSizeThreshold;
- public int mStreamUseCase;
+ public long mStreamUseCase;
public StreamTemplate(int format, SizeThreshold sizeThreshold) {
this(format, sizeThreshold, CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
}
public StreamTemplate(@Format int format, @NonNull SizeThreshold sizeThreshold,
- @StreamUseCase int streamUseCase) {
+ @StreamUseCase long streamUseCase) {
mFormat = format;
mSizeThreshold = sizeThreshold;
mStreamUseCase = streamUseCase;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 2350b7c..39cb7f3 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -918,9 +918,9 @@
* @throws IllegalArgumentException If the streamUseCase isn't within the range of valid
* values.
*/
- public void setStreamUseCase(@StreamUseCase int streamUseCase) {
+ public void setStreamUseCase(@StreamUseCase long streamUseCase) {
// Verify that the value is in range
- int maxUseCaseValue = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
+ long maxUseCaseValue = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
if (streamUseCase > maxUseCaseValue &&
streamUseCase < CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START) {
throw new IllegalArgumentException("Not a valid stream use case value " +
@@ -938,7 +938,7 @@
*
* @return the currently set stream use case
*/
- public int getStreamUseCase() {
+ public long getStreamUseCase() {
return mStreamUseCase;
}
@@ -1067,7 +1067,7 @@
String physicalCameraId = source.readString();
boolean isMultiResolutionOutput = source.readInt() == 1;
int[] sensorPixelModesUsed = source.createIntArray();
- int streamUseCase = source.readInt();
+ long streamUseCase = source.readLong();
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
long dynamicRangeProfile = source.readLong();
@@ -1218,7 +1218,7 @@
// writeList doesn't seem to work well with Integer list.
dest.writeIntArray(convertIntegerToIntList(mSensorPixelModesUsed));
dest.writeLong(mDynamicRangeProfile);
- dest.writeInt(mStreamUseCase);
+ dest.writeLong(mStreamUseCase);
dest.writeInt(mTimestampBase);
dest.writeInt(mMirrorMode);
}
@@ -1337,7 +1337,7 @@
// Dynamic range profile
private long mDynamicRangeProfile;
// Stream use case
- private int mStreamUseCase;
+ private long mStreamUseCase;
// Timestamp base
private int mTimestampBase;
// Mirroring mode
diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
index 2dd3aaa1..5c9989e 100644
--- a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
+++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
@@ -27,6 +27,7 @@
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.annotation.NonNull;
+import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.net.NetworkIdentity;
import android.net.NetworkStatsCollection;
@@ -47,6 +48,8 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -76,6 +79,15 @@
*/
public static final String PREFIX_UID_TAG = "uid_tag";
+ /** @hide */
+ @StringDef(prefix = {"PREFIX_"}, value = {
+ PREFIX_XT,
+ PREFIX_UID,
+ PREFIX_UID_TAG,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Prefix {}
+
private static final HashMap<String, String> sPrefixLegacyFileNameMap =
new HashMap<String, String>() {{
put(PREFIX_XT, "netstats_xt.bin");
@@ -141,13 +153,13 @@
// Get /data/system/netstats_*.bin legacy files. Does not check for existence.
@NonNull
- private static File getLegacyBinFileForPrefix(@NonNull String prefix) {
+ private static File getLegacyBinFileForPrefix(@NonNull @Prefix String prefix) {
return new File(getPlatformSystemDir(), sPrefixLegacyFileNameMap.get(prefix));
}
// List /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files.
@NonNull
- private static ArrayList<File> getPlatformFileListForPrefix(@NonNull String prefix) {
+ private static ArrayList<File> getPlatformFileListForPrefix(@NonNull @Prefix String prefix) {
final ArrayList<File> list = new ArrayList<>();
final File platformFiles = new File(getPlatformBaseDir(), "netstats");
if (platformFiles.exists()) {
@@ -207,7 +219,7 @@
*/
@NonNull
public static NetworkStatsCollection readPlatformCollection(
- @NonNull String prefix, long bucketDuration) throws IOException {
+ @NonNull @Prefix String prefix, long bucketDuration) throws IOException {
final NetworkStatsCollection.Builder builder =
new NetworkStatsCollection.Builder(bucketDuration);
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8263149..68d1a0b 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2702,6 +2702,46 @@
@ServiceState.FrequencyRange int frequencyRange, int signalStrength,
long elapsedRealtimeMs);
+ /**
+ * Returns the time in microseconds that the mobile radio has been actively transmitting data on
+ * a given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
+ * transmission power level.
+ *
+ * @param rat Radio Access Technology {@see RadioAccessTechnology}
+ * @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for
+ * RADIO_ACCESS_TECHNOLOGY_NR. Use
+ * {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access
+ * Technologies.
+ * @param signalStrength the cellular signal strength. {@see CellSignalStrength#getLevel()}
+ * @param elapsedRealtimeMs current elapsed realtime
+ * @return time (in milliseconds) the mobile radio spent actively transmitting data in the
+ * specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if
+ * data unavailable.
+ * @hide
+ */
+ public abstract long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
+ long elapsedRealtimeMs);
+
+ /**
+ * Returns the time in microseconds that the mobile radio has been actively receiving data on a
+ * given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
+ * transmission power level.
+ *
+ * @param rat Radio Access Technology {@see RadioAccessTechnology}
+ * @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for
+ * RADIO_ACCESS_TECHNOLOGY_NR. Use
+ * {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access
+ * Technologies.
+ * @param elapsedRealtimeMs current elapsed realtime
+ * @return time (in milliseconds) the mobile radio spent actively receiving data in the
+ * specified state, while on battery. Returns {@link DURATION_UNAVAILABLE} if
+ * data unavailable.
+ * @hide
+ */
+ public abstract long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs);
+
static final String[] WIFI_SUPPL_STATE_NAMES = {
"invalid", "disconn", "disabled", "inactive", "scanning",
"authenticating", "associating", "associated", "4-way-handshake",
@@ -2722,6 +2762,13 @@
public static final long POWER_DATA_UNAVAILABLE = -1L;
/**
+ * Returned value if duration data is unavailable.
+ *
+ * {@hide}
+ */
+ public static final long DURATION_UNAVAILABLE = -1L;
+
+ /**
* Returns the battery consumption (in microcoulombs) of bluetooth, derived from on
* device power measurement data.
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
@@ -4095,6 +4142,10 @@
" Mmwave frequency (greater than 6GHz):\n"};
final String signalStrengthHeader =
" Signal Strength Time:\n";
+ final String txHeader =
+ " Tx Time:\n";
+ final String rxHeader =
+ " Rx Time: ";
final String[] signalStrengthDescription = new String[]{
" unknown: ",
" poor: ",
@@ -4146,6 +4197,29 @@
sb.append(")\n");
}
+ sb.append(prefix);
+ sb.append(txHeader);
+ for (int strength = 0; strength < numSignalStrength; strength++) {
+ final long timeMs = getActiveTxRadioDurationMs(rat, freqLvl, strength,
+ rawRealtimeMs);
+ if (timeMs <= 0) continue;
+ hasFreqData = true;
+ sb.append(prefix);
+ sb.append(signalStrengthDescription[strength]);
+ formatTimeMs(sb, timeMs);
+ sb.append("(");
+ sb.append(formatRatioLocked(timeMs, totalActiveTimesMs));
+ sb.append(")\n");
+ }
+
+ sb.append(prefix);
+ sb.append(rxHeader);
+ final long rxTimeMs = getActiveRxRadioDurationMs(rat, freqLvl, rawRealtimeMs);
+ formatTimeMs(sb, rxTimeMs);
+ sb.append("(");
+ sb.append(formatRatioLocked(rxTimeMs, totalActiveTimesMs));
+ sb.append(")\n");
+
if (hasFreqData) {
hasData = true;
pw.print(sb);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 276578e..2448a05 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1703,12 +1703,40 @@
/**
* A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
- * an error occurred that prevented the user from being removed or set as ephemeral.
+ * an unknown error occurred that prevented the user from being removed or set as ephemeral.
*
* @hide
*/
@SystemApi
- public static final int REMOVE_RESULT_ERROR = 3;
+ public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1;
+
+ /**
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * the user could not be removed due to a {@link #DISALLOW_REMOVE_MANAGED_PROFILE} or
+ * {@link #DISALLOW_REMOVE_USER} user restriction.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int REMOVE_RESULT_ERROR_USER_RESTRICTION = -2;
+
+ /**
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * user being removed does not exist.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3;
+
+ /**
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * user being removed is a {@link UserHandle#SYSTEM} user which can't be removed.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4;
/**
* Possible response codes from {@link #removeUserWhenPossible(UserHandle, boolean)}.
@@ -1719,7 +1747,10 @@
REMOVE_RESULT_REMOVED,
REMOVE_RESULT_DEFERRED,
REMOVE_RESULT_ALREADY_BEING_REMOVED,
- REMOVE_RESULT_ERROR,
+ REMOVE_RESULT_ERROR_USER_RESTRICTION,
+ REMOVE_RESULT_ERROR_USER_NOT_FOUND,
+ REMOVE_RESULT_ERROR_SYSTEM_USER,
+ REMOVE_RESULT_ERROR_UNKNOWN,
})
@Retention(RetentionPolicy.SOURCE)
public @interface RemoveResult {}
@@ -4846,8 +4877,10 @@
* the {@link #DISALLOW_REMOVE_USER} or {@link #DISALLOW_REMOVE_MANAGED_PROFILE} restriction
*
* @return the {@link RemoveResult} code: {@link #REMOVE_RESULT_REMOVED},
- * {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED}, or
- * {@link #REMOVE_RESULT_ERROR}.
+ * {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED},
+ * {@link #REMOVE_RESULT_ERROR_USER_RESTRICTION}, {@link #REMOVE_RESULT_ERROR_USER_NOT_FOUND},
+ * {@link #REMOVE_RESULT_ERROR_SYSTEM_USER}, or {@link #REMOVE_RESULT_ERROR_UNKNOWN}. All error
+ * codes have negative values.
*
* @hide
*/
@@ -4864,6 +4897,19 @@
}
/**
+ * Check if {@link #removeUserWhenPossible} returned a success code which means that the user
+ * has been removed or is slated for removal.
+ *
+ * @param result is {@link #RemoveResult} code return by {@link #removeUserWhenPossible}.
+ * @return {@code true} if it is a success code.
+ * @hide
+ */
+ @SystemApi
+ public static boolean isRemoveResultSuccessful(@RemoveResult int result) {
+ return result >= 0;
+ }
+
+ /**
* Updates the user's name.
*
* @param userId the user's integer id
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 7832dcc..c021c07 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -78,37 +78,10 @@
*/
String getMountedObbPath(in String rawPath) = 24;
/**
- * Decrypts any encrypted volumes.
- */
- int decryptStorage(in String password) = 26;
- /**
- * Encrypts storage.
- */
- int encryptStorage(int type, in String password) = 27;
- /**
- * Changes the encryption password.
- */
- int changeEncryptionPassword(int type, in String password) = 28;
- /**
* Returns list of all mountable volumes for the specified userId
*/
StorageVolume[] getVolumeList(int userId, in String callingPackage, int flags) = 29;
/**
- * Determines the encryption state of the volume.
- * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
- * values.
- * Note that this has been replaced in most cases by the APIs in
- * StorageManager (see isEncryptable and below)
- * This is still useful to get the error state when encryption has failed
- * and CryptKeeper needs to throw up a screen advising the user what to do
- */
- int getEncryptionState() = 31;
- /**
- * Verify the encryption password against the stored volume. This method
- * may only be called by the system process.
- */
- int verifyEncryptionPassword(in String password) = 32;
- /**
* Ensure that all directories along given path exist, creating parent
* directories as needed. Validates that given path is absolute and that it
* contains no relative "." or ".." paths or symlinks. Also ensures that
@@ -117,32 +90,6 @@
*/
void mkdirs(in String callingPkg, in String path) = 34;
/**
- * Determines the type of the encryption password
- * @return PasswordType
- */
- int getPasswordType() = 35;
- /**
- * Get password from vold
- * @return password or empty string
- */
- String getPassword() = 36;
- /**
- * Securely clear password from vold
- */
- oneway void clearPassword() = 37;
- /**
- * Set a field in the crypto header.
- * @param field field to set
- * @param contents contents to set in field
- */
- oneway void setField(in String field, in String contents) = 38;
- /**
- * Gets a field from the crypto header.
- * @param field field to get
- * @return contents of field
- */
- String getField(in String field) = 39;
- /**
* Report the time of the last maintenance operation such as fstrim.
* @return Timestamp of the last maintenance operation, in the
* System.currentTimeMillis() time base
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 312abf8..9971cbc 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -3044,14 +3044,4 @@
public static final int CRYPT_TYPE_PATTERN = IVold.PASSWORD_TYPE_PATTERN;
/** @hide */
public static final int CRYPT_TYPE_PIN = IVold.PASSWORD_TYPE_PIN;
-
- // Constants for the data available via StorageManagerService.getField.
- /** @hide */
- public static final String SYSTEM_LOCALE_KEY = "SystemLocale";
- /** @hide */
- public static final String OWNER_INFO_KEY = "OwnerInfo";
- /** @hide */
- public static final String PATTERN_VISIBLE_KEY = "PatternVisible";
- /** @hide */
- public static final String PASSWORD_VISIBLE_KEY = "PasswordVisible";
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index a2938a8..ef792d4 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -252,6 +252,7 @@
final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
+ final Bundle mSyncSeqIdBundle = new Bundle();
private final Point mSurfaceSize = new Point();
private final Point mLastSurfaceSize = new Point();
private final Matrix mTmpMatrix = new Matrix();
@@ -391,7 +392,7 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {
Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
reportDraw ? 1 : 0,
mergedConfiguration);
@@ -1151,7 +1152,7 @@
final int relayoutResult = mSession.relayout(
mWindow, mLayout, mWidth, mHeight,
View.VISIBLE, 0, mWinFrames, mMergedConfiguration, mSurfaceControl,
- mInsetsState, mTempControls);
+ mInsetsState, mTempControls, mSyncSeqIdBundle);
final int transformHint = SurfaceControl.rotationToBufferTransform(
(mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
@@ -1338,7 +1339,8 @@
mSurfaceCreated = true;
if (redrawNeeded) {
resetWindowPages();
- mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+ mSession.finishDrawing(mWindow, null /* postDrawTransaction */,
+ Integer.MAX_VALUE);
processLocalColors(mPendingXOffset, mPendingXOffsetStep);
notifyColorsChanged();
}
diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java
index 9307e56..f31a690 100644
--- a/core/java/android/text/PrecomputedText.java
+++ b/core/java/android/text/PrecomputedText.java
@@ -99,7 +99,7 @@
private final @Layout.HyphenationFrequency int mHyphenationFrequency;
// The line break configuration for calculating text wrapping.
- private final @Nullable LineBreakConfig mLineBreakConfig;
+ private final @NonNull LineBreakConfig mLineBreakConfig;
/**
* A builder for creating {@link Params}.
@@ -119,7 +119,7 @@
Layout.HYPHENATION_FREQUENCY_NORMAL;
// The line break configuration for calculating text wrapping.
- private @Nullable LineBreakConfig mLineBreakConfig;
+ private @NonNull LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
/**
* Builder constructor.
@@ -212,7 +212,7 @@
// For the external developers, use Builder instead.
/** @hide */
public Params(@NonNull TextPaint paint,
- @Nullable LineBreakConfig lineBreakConfig,
+ @NonNull LineBreakConfig lineBreakConfig,
@NonNull TextDirectionHeuristic textDir,
@Layout.BreakStrategy int strategy,
@Layout.HyphenationFrequency int frequency) {
@@ -260,11 +260,12 @@
}
/**
- * Return the line break configuration for this text.
+ * Returns the {@link LineBreakConfig} for this text.
*
- * @return the current line break configuration, null if no line break configuration is set.
+ * @return the current line break configuration. The {@link LineBreakConfig} with default
+ * values will be returned if no line break configuration is set.
*/
- public @Nullable LineBreakConfig getLineBreakConfig() {
+ public @NonNull LineBreakConfig getLineBreakConfig() {
return mLineBreakConfig;
}
@@ -297,9 +298,9 @@
/** @hide */
public @CheckResultUsableResult int checkResultUsable(@NonNull TextPaint paint,
@NonNull TextDirectionHeuristic textDir, @Layout.BreakStrategy int strategy,
- @Layout.HyphenationFrequency int frequency, @Nullable LineBreakConfig lbConfig) {
+ @Layout.HyphenationFrequency int frequency, @NonNull LineBreakConfig lbConfig) {
if (mBreakStrategy == strategy && mHyphenationFrequency == frequency
- && isLineBreakEquals(mLineBreakConfig, lbConfig)
+ && mLineBreakConfig.equals(lbConfig)
&& mPaint.equalsForTextMeasurement(paint)) {
return mTextDir == textDir ? USABLE : NEED_RECOMPUTE;
} else {
@@ -308,29 +309,6 @@
}
/**
- * Check the two LineBreakConfig instances are equal.
- * This method assumes they are equal if one parameter is null and the other parameter has
- * a LineBreakStyle value of LineBreakConfig.LINE_BREAK_STYLE_NONE.
- *
- * @param o1 the first LineBreakConfig instance.
- * @param o2 the second LineBreakConfig instance.
- * @return true if the two LineBreakConfig instances are equal.
- */
- private boolean isLineBreakEquals(LineBreakConfig o1, LineBreakConfig o2) {
- if (Objects.equals(o1, o2)) {
- return true;
- }
- if (o1 == null && (o2 != null
- && o2.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) {
- return true;
- } else if (o2 == null && (o1 != null
- && o1.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) {
- return true;
- }
- return false;
- }
-
- /**
* Check if the same text layout.
*
* @return true if this and the given param result in the same text layout
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index b10fc37..2f85d2b6 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -112,6 +112,7 @@
b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
+ b.mLineBreakConfig = LineBreakConfig.NONE;
return b;
}
@@ -410,7 +411,8 @@
*
* @param lineBreakConfig the line break configuration for text wrapping.
* @return this builder, useful for chaining.
- * @see android.widget.TextView#setLineBreakConfig
+ * @see android.widget.TextView#setLineBreakStyle
+ * @see android.widget.TextView#setLineBreakWordStyle
*/
@NonNull
public Builder setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
@@ -454,7 +456,7 @@
@Nullable private int[] mRightIndents;
private int mJustificationMode;
private boolean mAddLastLineLineSpacing;
- private LineBreakConfig mLineBreakConfig;
+ private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index c1413be..190adbd 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -249,19 +249,19 @@
return;
}
- Rect handwritingArea = getViewHandwritingArea(connectedView);
- if (handwritingArea != null) {
- if (contains(handwritingArea, mState.mStylusDownX, mState.mStylusDownY)) {
- startHandwriting(connectedView);
- }
+ final Rect handwritingArea = getViewHandwritingArea(connectedView);
+ if (contains(handwritingArea, mState.mStylusDownX, mState.mStylusDownY)) {
+ startHandwriting(connectedView);
+ } else {
+ reset();
}
- reset();
}
/** For test only. */
@VisibleForTesting
public void startHandwriting(@NonNull View view) {
mImm.startStylusHandwriting(view);
+ reset();
}
/**
@@ -287,7 +287,7 @@
final View connectedView = getConnectedView();
if (connectedView != null && connectedView.isAutoHandwritingEnabled()) {
final Rect handwritingArea = getViewHandwritingArea(connectedView);
- if (handwritingArea != null && contains(handwritingArea, x, y)) {
+ if (contains(handwritingArea, x, y)) {
return connectedView;
}
}
@@ -298,8 +298,7 @@
for (HandwritableViewInfo viewInfo : handwritableViewInfos) {
final View view = viewInfo.getView();
if (!view.isAutoHandwritingEnabled()) continue;
- final Rect rect = viewInfo.getHandwritingArea();
- if (rect != null && contains(rect, x, y)) {
+ if (contains(viewInfo.getHandwritingArea(), x, y)) {
return viewInfo.getView();
}
}
@@ -315,12 +314,15 @@
private static Rect getViewHandwritingArea(@NonNull View view) {
final ViewParent viewParent = view.getParent();
if (viewParent != null && view.isAttachedToWindow() && view.isAggregatedVisible()) {
- Rect handwritingArea = view.getHandwritingArea();
- if (handwritingArea == null) {
- handwritingArea = new Rect(0, 0, view.getWidth(), view.getHeight());
+ final Rect localHandwritingArea = view.getHandwritingArea();
+ final Rect globalHandwritingArea = new Rect();
+ if (localHandwritingArea != null) {
+ globalHandwritingArea.set(localHandwritingArea);
+ } else {
+ globalHandwritingArea.set(0, 0, view.getWidth(), view.getHeight());
}
- if (viewParent.getChildVisibleRect(view, handwritingArea, null)) {
- return handwritingArea;
+ if (viewParent.getChildVisibleRect(view, globalHandwritingArea, null)) {
+ return globalHandwritingArea;
}
}
return null;
@@ -329,7 +331,8 @@
/**
* Return true if the (x, y) is inside by the given {@link Rect}.
*/
- private boolean contains(@NonNull Rect rect, float x, float y) {
+ private boolean contains(@Nullable Rect rect, float x, float y) {
+ if (rect == null) return false;
return x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom;
}
@@ -481,17 +484,18 @@
if (!mIsDirty) {
return true;
}
- final Rect localRect = view.getHandwritingArea();
- if (localRect == null) {
+ final Rect handwritingArea = view.getHandwritingArea();
+ if (handwritingArea == null) {
return false;
}
ViewParent parent = view.getParent();
if (parent != null) {
- final Rect newRect = new Rect(localRect);
- if (parent.getChildVisibleRect(view, newRect, null /* offset */)) {
- mHandwritingArea = newRect;
- } else {
+ if (mHandwritingArea == null) {
+ mHandwritingArea = new Rect();
+ }
+ mHandwritingArea.set(handwritingArea);
+ if (!parent.getChildVisibleRect(view, mHandwritingArea, null /* offset */)) {
mHandwritingArea = null;
}
}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 12421ed..1f6cee6 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -55,7 +55,8 @@
void resized(in ClientWindowFrames frames, boolean reportDraw,
in MergedConfiguration newMergedConfiguration,
- boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId);
+ boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
+ int syncSeqId);
/**
* Called when the window insets configuration has changed.
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 5c7c844..fd86900 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -104,7 +104,8 @@
int requestedWidth, int requestedHeight, int viewVisibility,
int flags, out ClientWindowFrames outFrames,
out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
- out InsetsState insetsState, out InsetsSourceControl[] activeControls);
+ out InsetsState insetsState, out InsetsSourceControl[] activeControls,
+ out Bundle bundle);
/*
* Notify the window manager that an application is relaunching and
@@ -142,7 +143,8 @@
* is null if there is no sync required.
*/
@UnsupportedAppUsage
- oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction);
+ oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction,
+ int seqId);
@UnsupportedAppUsage
oneway void setInTouchMode(boolean showFocus);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c222991..0a61f28e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12016,7 +12016,6 @@
/**
* Return the handwriting areas set on this view, in its local coordinates.
- * Notice: the caller of this method should not modify the Rect returned.
* @see #setHandwritingArea(Rect)
*
* @hide
@@ -12025,7 +12024,7 @@
public Rect getHandwritingArea() {
final ListenerInfo info = mListenerInfo;
if (info != null) {
- return info.mHandwritingArea;
+ return new Rect(info.mHandwritingArea);
}
return null;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e79bdce..6ed172b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -830,6 +830,24 @@
private int mLastTransformHint = Integer.MIN_VALUE;
+ /**
+ * A temporary object used so relayoutWindow can return the latest SyncSeqId
+ * system. The SyncSeqId system was designed to work without synchronous relayout
+ * window, and actually synchronous relayout window presents a problem. We could have
+ * a sequence like this:
+ * 1. We send MSG_RESIZED to the client with a new syncSeqId to begin a new sync
+ * 2. Due to scheduling the client executes performTraversals before calling MSG_RESIZED
+ * 3. Coincidentally for some random reason it also calls relayout
+ * 4. It observes the new state from relayout, and so the next frame will contain the state
+ * However it hasn't received the seqId yet, and so under the designed operation of
+ * seqId flowing through MSG_RESIZED, the next frame wouldn't be synced. Since it
+ * contains our target sync state, we need to sync it! This problem won't come up once
+ * we get rid of synchronous relayout, until then, we use this bundle to channel the
+ * integer back over relayout.
+ */
+ private Bundle mRelayoutBundle = new Bundle();
+ private int mSyncSeqId;
+
private String mTag = TAG;
public ViewRootImpl(Context context, Display display) {
@@ -1711,6 +1729,7 @@
mPendingBackDropFrame.set(backdropFrame);
mForceNextWindowRelayout = forceNextWindowRelayout;
mPendingAlwaysConsumeSystemBars = args.argi2 != 0;
+ mSyncSeqId = args.argi4;
if (msg == MSG_RESIZED_REPORT) {
reportNextDraw();
@@ -4128,7 +4147,7 @@
mDrawsNeededToReport = 0;
try {
- mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction);
+ mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, Integer.MAX_VALUE);
} catch (RemoteException e) {
Log.e(mTag, "Unable to report draw finished", e);
mSurfaceChangedTransaction.apply();
@@ -8071,7 +8090,7 @@
requestedWidth, requestedHeight, viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
- mTempControls);
+ mTempControls, mRelayoutBundle);
final int transformHint = SurfaceControl.rotationToBufferTransform(
(mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
@@ -8497,7 +8516,7 @@
if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
& WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
mWindowSession.finishDrawing(
- mWindow, null /* postDrawTransaction */);
+ mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE);
}
} catch (RemoteException e) {
}
@@ -8571,7 +8590,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void dispatchResized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int seqId) {
final Rect frame = frames.frame;
final Rect backDropFrame = frames.backdropFrame;
if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
@@ -8602,6 +8621,7 @@
args.argi1 = forceLayout ? 1 : 0;
args.argi2 = alwaysConsumeSystemBars ? 1 : 0;
args.argi3 = displayId;
+ args.argi4 = seqId;
msg.obj = args;
mHandler.sendMessage(msg);
}
@@ -9986,11 +10006,11 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int seqId) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, forceLayout,
- alwaysConsumeSystemBars, displayId);
+ alwaysConsumeSystemBars, displayId, seqId);
}
}
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index a270c92..ad151df 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -22,6 +22,7 @@
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -217,9 +218,13 @@
throw new IllegalArgumentException(
"Invalid window token (never added or removed already)");
}
+ removeSurface(state.mSurfaceControl);
+ }
+ /** Separate from {@link #remove} so that subclasses can put removal on a sync transaction. */
+ protected void removeSurface(SurfaceControl sc) {
try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
- t.remove(state.mSurfaceControl).apply();
+ t.remove(sc).apply();
}
}
@@ -277,7 +282,7 @@
int requestedWidth, int requestedHeight, int viewFlags, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
- InsetsSourceControl[] outActiveControls) {
+ InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {
final State state;
synchronized (this) {
state = mStateForWindow.get(window.asBinder());
@@ -354,7 +359,7 @@
@Override
public void finishDrawing(android.view.IWindow window,
- android.view.SurfaceControl.Transaction postDrawTransaction) {
+ android.view.SurfaceControl.Transaction postDrawTransaction, int seqId) {
synchronized (this) {
final ResizeCompleteCallback c =
mResizeCompletionForWindow.get(window.asBinder());
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b076d39..3c8fcb9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -788,7 +788,8 @@
private Layout mLayout;
private boolean mLocalesChanged = false;
private int mTextSizeUnit = -1;
- private LineBreakConfig mLineBreakConfig = new LineBreakConfig();
+ private int mLineBreakStyle = DEFAULT_LINE_BREAK_STYLE;
+ private int mLineBreakWordStyle = DEFAULT_LINE_BREAK_WORD_STYLE;
// This is used to reflect the current user preference for changing font weight and making text
// more bold.
@@ -1457,13 +1458,12 @@
break;
case com.android.internal.R.styleable.TextView_lineBreakStyle:
- mLineBreakConfig.setLineBreakStyle(
- a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE));
+ mLineBreakStyle = a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE);
break;
case com.android.internal.R.styleable.TextView_lineBreakWordStyle:
- mLineBreakConfig.setLineBreakWordStyle(
- a.getInt(attr, LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE));
+ mLineBreakWordStyle = a.getInt(attr,
+ LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE);
break;
case com.android.internal.R.styleable.TextView_autoSizeTextType:
@@ -4301,13 +4301,12 @@
@LineBreakConfig.LineBreakStyle int lineBreakStyle,
@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) {
boolean updated = false;
- if (isLineBreakStyleSpecified && mLineBreakConfig.getLineBreakStyle() != lineBreakStyle) {
- mLineBreakConfig.setLineBreakStyle(lineBreakStyle);
+ if (isLineBreakStyleSpecified && mLineBreakStyle != lineBreakStyle) {
+ mLineBreakStyle = lineBreakStyle;
updated = true;
}
- if (isLineBreakWordStyleSpecified
- && mLineBreakConfig.getLineBreakWordStyle() != lineBreakWordStyle) {
- mLineBreakConfig.setLineBreakWordStyle(lineBreakWordStyle);
+ if (isLineBreakWordStyleSpecified && mLineBreakWordStyle != lineBreakWordStyle) {
+ mLineBreakWordStyle = lineBreakWordStyle;
updated = true;
}
if (updated && mLayout != null) {
@@ -4871,50 +4870,72 @@
}
/**
- * Sets line break configuration indicates which strategy needs to be used when calculating the
- * text wrapping.
- * <P>
- * There are two types of line break rules that can be configured at the same time. One is
- * line break style(lb) and the other is line break word style(lw). The line break style
- * affects rule-based breaking. The line break word style affects dictionary-based breaking
- * and provide phrase-based breaking opportunities. There are several types for the
- * line break style:
+ * Set the line break style for text wrapping.
+ *
+ * The line break style to indicates the line break strategies can be used when
+ * calculating the text wrapping. The line break style affects rule-based breaking. It
+ * specifies the strictness of line-breaking rules.
+ * There are several types for the line break style:
* {@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE},
* {@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL} and
- * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}.
- * The type for the line break word style is
- * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}.
- * The default values of the line break style and the line break word style are
- * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE} and
- * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE} respectively, indicating that no line
- * breaking rules are specified.
- * See <a href="https://drafts.csswg.org/css-text/#line-break-property">
+ * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}. The default values of the line break style
+ * is {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}, indicating no breaking rule is specified.
+ * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">
* the line-break property</a>
*
- * @param lineBreakConfig the line break config for text wrapping.
+ * @param lineBreakStyle the line break style for the text.
*/
- public void setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
- Objects.requireNonNull(lineBreakConfig);
- if (mLineBreakConfig.equals(lineBreakConfig)) {
- return;
- }
- mLineBreakConfig.set(lineBreakConfig);
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
+ public void setLineBreakStyle(@LineBreakConfig.LineBreakStyle int lineBreakStyle) {
+ if (mLineBreakStyle != lineBreakStyle) {
+ mLineBreakStyle = lineBreakStyle;
+ if (mLayout != null) {
+ nullLayouts();
+ requestLayout();
+ invalidate();
+ }
}
}
/**
- * Get the current line break configuration for text wrapping.
+ * Set the line break word style for text wrapping.
*
- * @return the current line break configuration to be used for text wrapping.
+ * The line break word style affects dictionary-based breaking and provide phrase-based
+ * breaking opportunities. The type for the line break word style is
+ * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}. The default values of the line break
+ * word style is {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}, indicating no breaking rule
+ * is specified.
+ * See <a href="https://www.w3.org/TR/css-text-3/#word-break-property">
+ * the word-break property</a>
+ *
+ * @param lineBreakWordStyle the line break word style for the tet
*/
- public @NonNull LineBreakConfig getLineBreakConfig() {
- LineBreakConfig lbConfig = new LineBreakConfig();
- lbConfig.set(mLineBreakConfig);
- return lbConfig;
+ public void setLineBreakWordStyle(@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) {
+ if (mLineBreakWordStyle != lineBreakWordStyle) {
+ mLineBreakWordStyle = lineBreakWordStyle;
+ if (mLayout != null) {
+ nullLayouts();
+ requestLayout();
+ invalidate();
+ }
+ }
+ }
+
+ /**
+ * Get the current line break style for text wrapping.
+ *
+ * @return the current line break style to be used for text wrapping.
+ */
+ public @LineBreakConfig.LineBreakStyle int getLineBreakStyle() {
+ return mLineBreakStyle;
+ }
+
+ /**
+ * Get the current line word break style for text wrapping.
+ *
+ * @return the current line break word style to be used for text wrapping.
+ */
+ public @LineBreakConfig.LineBreakWordStyle int getLineBreakWordStyle() {
+ return mLineBreakWordStyle;
}
/**
@@ -4924,7 +4945,8 @@
* @see PrecomputedText
*/
public @NonNull PrecomputedText.Params getTextMetricsParams() {
- return new PrecomputedText.Params(new TextPaint(mTextPaint), mLineBreakConfig,
+ return new PrecomputedText.Params(new TextPaint(mTextPaint),
+ LineBreakConfig.getLineBreakConfig(mLineBreakStyle, mLineBreakWordStyle),
getTextDirectionHeuristic(),
mBreakStrategy, mHyphenationFrequency);
}
@@ -4941,13 +4963,9 @@
mTextDir = params.getTextDirection();
mBreakStrategy = params.getBreakStrategy();
mHyphenationFrequency = params.getHyphenationFrequency();
- if (params.getLineBreakConfig() != null) {
- mLineBreakConfig.set(params.getLineBreakConfig());
- } else {
- // Set default value if the line break config in the PrecomputedText.Params is null.
- mLineBreakConfig.setLineBreakStyle(DEFAULT_LINE_BREAK_STYLE);
- mLineBreakConfig.setLineBreakWordStyle(DEFAULT_LINE_BREAK_WORD_STYLE);
- }
+ LineBreakConfig lineBreakConfig = params.getLineBreakConfig();
+ mLineBreakStyle = lineBreakConfig.getLineBreakStyle();
+ mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle();
if (mLayout != null) {
nullLayouts();
requestLayout();
@@ -6486,7 +6504,8 @@
}
final @PrecomputedText.Params.CheckResultUsableResult int checkResult =
precomputed.getParams().checkResultUsable(getPaint(), mTextDir, mBreakStrategy,
- mHyphenationFrequency, mLineBreakConfig);
+ mHyphenationFrequency, LineBreakConfig.getLineBreakConfig(
+ mLineBreakStyle, mLineBreakWordStyle));
switch (checkResult) {
case PrecomputedText.Params.UNUSABLE:
throw new IllegalArgumentException(
@@ -9383,7 +9402,8 @@
.setHyphenationFrequency(mHyphenationFrequency)
.setJustificationMode(mJustificationMode)
.setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
- .setLineBreakConfig(mLineBreakConfig);
+ .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+ mLineBreakStyle, mLineBreakWordStyle));
if (shouldEllipsize) {
builder.setEllipsize(mEllipsize)
.setEllipsizedWidth(ellipsisWidth);
@@ -9498,7 +9518,8 @@
.setHyphenationFrequency(mHyphenationFrequency)
.setJustificationMode(mJustificationMode)
.setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
- .setLineBreakConfig(mLineBreakConfig);
+ .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+ mLineBreakStyle, mLineBreakWordStyle));
if (shouldEllipsize) {
builder.setEllipsize(effectiveEllipsize)
.setEllipsizedWidth(ellipsisWidth);
@@ -9866,7 +9887,8 @@
.setJustificationMode(getJustificationMode())
.setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
.setTextDirection(getTextDirectionHeuristic())
- .setLineBreakConfig(mLineBreakConfig);
+ .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
+ mLineBreakStyle, mLineBreakWordStyle));
final StaticLayout layout = layoutBuilder.build();
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 5dbb551..d046cef 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -53,7 +53,7 @@
private static final String TAG = "WindowOnBackDispatcher";
private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
private static final boolean IS_BACK_PREDICTABILITY_ENABLED = SystemProperties
- .getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
+ .getInt(BACK_PREDICTABILITY_PROP, 1) > 0;
/** Convenience hashmap to quickly decide if a callback has been added. */
private final HashMap<OnBackInvokedCallback, Integer> mAllCallbacks = new HashMap<>();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index a5937a6..3b46f62 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -166,7 +166,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- static final int VERSION = 206;
+ static final int VERSION = 207;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -964,6 +964,16 @@
* Timers for each combination of frequency range and signal strength.
*/
public final StopwatchTimer[][] perStateTimers;
+ /**
+ * Counters tracking the time (in milliseconds) spent transmitting data in a given state.
+ */
+ @Nullable
+ private LongSamplingCounter[][] mPerStateTxDurationMs = null;
+ /**
+ * Counters tracking the time (in milliseconds) spent receiving data in at given frequency.
+ */
+ @Nullable
+ private LongSamplingCounter[] mPerFrequencyRxDurationMs = null;
RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
perStateTimers =
@@ -1024,15 +1034,198 @@
}
/**
- * Reset display timers.
+ * Returns the duration in milliseconds spent in a given state since the last mark.
+ */
+ public long getTimeSinceMark(@ServiceState.FrequencyRange int frequencyRange,
+ int signalStrength, long elapsedRealtimeMs) {
+ return perStateTimers[frequencyRange][signalStrength].getTimeSinceMarkLocked(
+ elapsedRealtimeMs * 1000) / 1000;
+ }
+
+ /**
+ * Set mark for all timers.
+ */
+ public void setMark(long elapsedRealtimeMs) {
+ final int size = perStateTimers.length;
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+ perStateTimers[i][j].setMark(elapsedRealtimeMs);
+ }
+ }
+ }
+
+ /**
+ * Returns numbers of frequencies tracked for this RAT.
+ */
+ public int getFrequencyRangeCount() {
+ return perStateTimers.length;
+ }
+
+ /**
+ * Add TX time for a given state.
+ */
+ public void incrementTxDuration(@ServiceState.FrequencyRange int frequencyRange,
+ int signalStrength, long durationMs) {
+ getTxDurationCounter(frequencyRange, signalStrength, true).addCountLocked(durationMs);
+ }
+
+ /**
+ * Add TX time for a given frequency.
+ */
+ public void incrementRxDuration(@ServiceState.FrequencyRange int frequencyRange,
+ long durationMs) {
+ getRxDurationCounter(frequencyRange, true).addCountLocked(durationMs);
+ }
+
+ /**
+ * Reset radio access technology timers and counts.
*/
public void reset(long elapsedRealtimeUs) {
final int size = perStateTimers.length;
for (int i = 0; i < size; i++) {
for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
perStateTimers[i][j].reset(false, elapsedRealtimeUs);
+ if (mPerStateTxDurationMs == null) continue;
+ mPerStateTxDurationMs[i][j].reset(false, elapsedRealtimeUs);
+ }
+ if (mPerFrequencyRxDurationMs == null) continue;
+ mPerFrequencyRxDurationMs[i].reset(false, elapsedRealtimeUs);
+ }
+ }
+
+ /**
+ * Write data to summary parcel
+ */
+ public void writeSummaryToParcel(Parcel out, long elapsedRealtimeUs) {
+ final int freqCount = perStateTimers.length;
+ out.writeInt(freqCount);
+ out.writeInt(CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS);
+ for (int i = 0; i < freqCount; i++) {
+ for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+ perStateTimers[i][j].writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
}
}
+
+ if (mPerStateTxDurationMs == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ for (int i = 0; i < freqCount; i++) {
+ for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+ mPerStateTxDurationMs[i][j].writeSummaryFromParcelLocked(out);
+ }
+ }
+ }
+
+ if (mPerFrequencyRxDurationMs == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ for (int i = 0; i < freqCount; i++) {
+ mPerFrequencyRxDurationMs[i].writeSummaryFromParcelLocked(out);
+ }
+ }
+ }
+
+ /**
+ * Read data from summary parcel
+ */
+ public void readSummaryFromParcel(Parcel in) {
+ final int oldFreqCount = in.readInt();
+ final int oldSignalStrengthCount = in.readInt();
+ final int currFreqCount = perStateTimers.length;
+ final int currSignalStrengthCount = CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS;
+
+ for (int freq = 0; freq < oldFreqCount; freq++) {
+ for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
+ if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
+ // Mismatch with the summary parcel. Consume the data but don't use it.
+ final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
+ new TimeBase());
+ // Consume perStateTimers data.
+ temp.readSummaryFromParcelLocked(in);
+ } else {
+ perStateTimers[freq][strength].readSummaryFromParcelLocked(in);
+ }
+ }
+ }
+
+ if (in.readInt() == 1) {
+ for (int freq = 0; freq < oldFreqCount; freq++) {
+ for (int strength = 0; strength < oldSignalStrengthCount; strength++) {
+ if (freq >= currFreqCount || strength >= currSignalStrengthCount) {
+ // Mismatch with the summary parcel. Consume the data but don't use it.
+ final StopwatchTimer temp = new StopwatchTimer(null, null, -1, null,
+ new TimeBase());
+ // Consume mPerStateTxDurationMs data.
+ temp.readSummaryFromParcelLocked(in);
+ }
+ getTxDurationCounter(freq, strength, true).readSummaryFromParcelLocked(in);
+ }
+ }
+ }
+
+ if (in.readInt() == 1) {
+ for (int freq = 0; freq < oldFreqCount; freq++) {
+ if (freq >= currFreqCount) {
+ // Mismatch with the summary parcel. Consume the data but don't use it.
+ final StopwatchTimer
+ temp = new StopwatchTimer(null, null, -1, null, new TimeBase());
+ // Consume mPerFrequencyRxDurationMs data.
+ temp.readSummaryFromParcelLocked(in);
+ continue;
+ }
+ getRxDurationCounter(freq, true).readSummaryFromParcelLocked(in);
+ }
+ }
+ }
+
+ private LongSamplingCounter getTxDurationCounter(
+ @ServiceState.FrequencyRange int frequencyRange, int signalStrength, boolean make) {
+ if (mPerStateTxDurationMs == null) {
+ if (!make) return null;
+
+ final int freqCount = getFrequencyRangeCount();
+ final int signalStrengthCount = perStateTimers[0].length;
+ final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
+ mPerStateTxDurationMs = new LongSamplingCounter[freqCount][signalStrengthCount];
+ for (int freq = 0; freq < freqCount; freq++) {
+ for (int strength = 0; strength < signalStrengthCount; strength++) {
+ mPerStateTxDurationMs[freq][strength] = new LongSamplingCounter(timeBase);
+ }
+ }
+ }
+ if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
+ Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
+ + ") requested in getTxDurationCounter");
+ return null;
+ }
+ if (signalStrength < 0 || signalStrength >= perStateTimers[0].length) {
+ Slog.w(TAG, "Unexpected signal strength (" + signalStrength
+ + ") requested in getTxDurationCounter");
+ return null;
+ }
+ return mPerStateTxDurationMs[frequencyRange][signalStrength];
+ }
+
+ private LongSamplingCounter getRxDurationCounter(
+ @ServiceState.FrequencyRange int frequencyRange, boolean make) {
+ if (mPerFrequencyRxDurationMs == null) {
+ if (!make) return null;
+
+ final int freqCount = getFrequencyRangeCount();
+ final TimeBase timeBase = perStateTimers[0][0].mTimeBase;
+ mPerFrequencyRxDurationMs = new LongSamplingCounter[freqCount];
+ for (int freq = 0; freq < freqCount; freq++) {
+ mPerFrequencyRxDurationMs[freq] = new LongSamplingCounter(timeBase);
+ }
+ }
+ if (frequencyRange < 0 || frequencyRange >= getFrequencyRangeCount()) {
+ Slog.w(TAG, "Unexpected frequency range (" + frequencyRange
+ + ") requested in getRxDurationCounter");
+ return null;
+ }
+ return mPerFrequencyRxDurationMs[frequencyRange];
}
}
@@ -8006,6 +8199,32 @@
elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
}
+ @Override
+ public long getActiveTxRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
+ long elapsedRealtimeMs) {
+ final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
+ if (stats == null) return DURATION_UNAVAILABLE;
+
+ final LongSamplingCounter counter = stats.getTxDurationCounter(frequencyRange,
+ signalStrength, false);
+ if (counter == null) return DURATION_UNAVAILABLE;
+
+ return counter.getCountLocked(STATS_SINCE_CHARGED);
+ }
+
+ @Override
+ public long getActiveRxRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, long elapsedRealtimeMs) {
+ final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
+ if (stats == null) return DURATION_UNAVAILABLE;
+
+ final LongSamplingCounter counter = stats.getRxDurationCounter(frequencyRange, false);
+ if (counter == null) return DURATION_UNAVAILABLE;
+
+ return counter.getCountLocked(STATS_SINCE_CHARGED);
+ }
+
@UnsupportedAppUsage
@Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
@@ -13484,6 +13703,67 @@
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mTmpRailStats.resetCellularTotalEnergyUsed();
}
+
+ // Proportionally smear Rx and Tx times across each RAt
+ final int levelCount = CellSignalStrength.getNumSignalStrengthLevels();
+ long[] perSignalStrengthActiveTimeMs = new long[levelCount];
+ long totalActiveTimeMs = 0;
+
+ for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+ final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
+ if (ratStats == null) continue;
+
+ final int freqCount = ratStats.getFrequencyRangeCount();
+ for (int freq = 0; freq < freqCount; freq++) {
+ for (int level = 0; level < levelCount; level++) {
+ final long durationMs = ratStats.getTimeSinceMark(freq, level,
+ elapsedRealtimeMs);
+ perSignalStrengthActiveTimeMs[level] += durationMs;
+ totalActiveTimeMs += durationMs;
+ }
+ }
+ }
+
+ if (totalActiveTimeMs != 0) {
+ // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
+ // strength.
+ for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+ final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
+ if (ratStats == null) continue;
+
+ final int freqCount = ratStats.getFrequencyRangeCount();
+ for (int freq = 0; freq < freqCount; freq++) {
+ long frequencyDurationMs = 0;
+ for (int level = 0; level < levelCount; level++) {
+ final long durationMs = ratStats.getTimeSinceMark(freq, level,
+ elapsedRealtimeMs);
+ final long totalLvlDurationMs =
+ perSignalStrengthActiveTimeMs[level];
+ if (totalLvlDurationMs == 0) continue;
+ final long totalTxLvlDurations =
+ deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
+ // Smear HAL provided Tx power level duration based on active modem
+ // duration in a given state. (Add totalLvlDurationMs / 2 before
+ // the integer division with totalLvlDurationMs for rounding.)
+ final long proportionalTxDurationMs =
+ (durationMs * totalTxLvlDurations
+ + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
+ ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
+ frequencyDurationMs += durationMs;
+ }
+ final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
+ // Smear HAL provided Rx power duration based on active modem
+ // duration in a given state. (Add totalActiveTimeMs / 2 before the
+ // integer division with totalActiveTimeMs for rounding.)
+ final long proportionalRxDurationMs =
+ (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
+ / 2)) / totalActiveTimeMs;
+ ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
+ }
+
+ ratStats.setMark(elapsedRealtimeMs);
+ }
+ }
}
long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000);
@@ -16932,6 +17212,13 @@
mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
}
+
+ final int numRat = in.readInt();
+ for (int i = 0; i < numRat; i++) {
+ if (in.readInt() == 0) continue;
+ getRatBatteryStatsLocked(i).readSummaryFromParcel(in);
+ }
+
mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
@@ -17432,6 +17719,17 @@
mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
}
+ final int numRat = mPerRatBatteryStats.length;
+ out.writeInt(numRat);
+ for (int i = 0; i < numRat; i++) {
+ final RadioAccessTechnologyBatteryStats ratStat = mPerRatBatteryStats[i];
+ if (ratStat == null) {
+ out.writeInt(0);
+ continue;
+ }
+ out.writeInt(1);
+ ratStat.writeSummaryToParcel(out, nowRealtime);
+ }
mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, nowRealtime);
mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, nowRealtime);
mMobileRadioActiveAdjustedTime.writeSummaryFromParcelLocked(out);
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 6673f67..842d72a 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -51,10 +51,10 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int seqId) {
if (reportDraw) {
try {
- mSession.finishDrawing(this, null /* postDrawTransaction */);
+ mSession.finishDrawing(this, null /* postDrawTransaction */, seqId);
} catch (RemoteException e) {
}
}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 851e8e0..3494c9e 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -53,7 +53,6 @@
VerifyCredentialResponse verifyTiedProfileChallenge(in LockscreenCredential credential, int userId, int flags);
VerifyCredentialResponse verifyGatekeeperPasswordHandle(long gatekeeperPasswordHandle, long challenge, int userId);
void removeGatekeeperPasswordHandle(long gatekeeperPasswordHandle);
- boolean checkVoldPassword(int userId);
int getCredentialType(int userId);
byte[] getHashFactor(in LockscreenCredential currentCredential, int userId);
void setSeparateProfileChallengeEnabled(int userId, boolean enabled, in LockscreenCredential managedUserPassword);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 521b2f6..a94b307 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -526,20 +526,6 @@
}
/**
- * Check to see if vold already has the password.
- * Note that this also clears vold's copy of the password.
- * @return Whether the vold password matches or not.
- */
- public boolean checkVoldPassword(int userId) {
- try {
- return getLockSettings().checkVoldPassword(userId);
- } catch (RemoteException re) {
- Log.e(TAG, "failed to check vold password", re);
- return false;
- }
- }
-
- /**
* Returns the password history hash factor, needed to check new password against password
* history with {@link #checkPasswordHistory(byte[], byte[], int)}
*/
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 4aa00f6..3a76745 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -361,7 +361,7 @@
"libwuffs_mirror_release_c",
],
},
- linux_glibc: {
+ host_linux: {
srcs: [
"android_content_res_ApkAssets.cpp",
"android_database_CursorWindow.cpp",
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index bbd6a5e3..b3203ae 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5479,9 +5479,9 @@
<enum name="none" value="0" />
<!-- Use the least restrictive rule for line-breaking. -->
<enum name="loose" value="1" />
- <!-- Indicate breaking text with the most comment set of line-breaking rules. -->
+ <!-- Indicates breaking text with the most comment set of line-breaking rules. -->
<enum name="normal" value="2" />
- <!-- ndicates breaking text with the most strictest line-breaking rules. -->
+ <!-- Indicates breaking text with the most strictest line-breaking rules. -->
<enum name="strict" value="3" />
</attr>
<!-- Specify the phrase-based line break can be used when calculating the text wrapping.-->
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 f5cbffb..7ccb9d9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -17,6 +17,8 @@
package com.android.internal.os;
import static android.os.BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
+import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
+import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
import static android.os.BatteryStats.STATS_SINCE_CHARGED;
import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
@@ -24,7 +26,10 @@
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY;
+import static org.mockito.Mockito.mock;
+
import android.app.ActivityManager;
+import android.app.usage.NetworkStatsManager;
import android.os.BatteryStats;
import android.os.BatteryStats.HistoryItem;
import android.os.BatteryStats.Uid.Sensor;
@@ -34,6 +39,7 @@
import android.telephony.Annotation;
import android.telephony.CellSignalStrength;
import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.ModemActivityInfo;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.util.SparseIntArray;
@@ -48,6 +54,8 @@
import junit.framework.TestCase;
+import org.mockito.Mock;
+
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -72,6 +80,13 @@
private static final int ISOLATED_UID = UserHandle.getUid(0, ISOLATED_APP_ID);
private static final WorkSource WS = new WorkSource(UID);
+ enum ModemState {
+ SLEEP, IDLE, RECEIVING, TRANSMITTING
+ }
+
+ @Mock
+ NetworkStatsManager mNetworkStatsManager;
+
/**
* Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked.
*/
@@ -1173,69 +1188,29 @@
}
@SmallTest
- public void testGetPerStateActiveRadioDurationMs() {
+ public void testGetPerStateActiveRadioDurationMs_noModemActivity() {
final MockClock clock = new MockClock(); // holds realtime and uptime in ms
final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
- final int ratCount = BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
+ final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+ final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
+ final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
for (int rat = 0; rat < ratCount; rat++) {
for (int freq = 0; freq < frequencyCount; freq++) {
+ // Should have no RX data without Modem Activity Info
+ expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
expectedDurationsMs[rat][freq][txLvl] = 0;
+ // Should have no TX data without Modem Activity Info
+ expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
}
}
}
- class ModemAndBatteryState {
- public long currentTimeMs = 100;
- public boolean onBattery = false;
- public boolean modemActive = false;
- @Annotation.NetworkType
- public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- @BatteryStats.RadioAccessTechnology
- public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
- @ServiceState.FrequencyRange
- public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
- public SparseIntArray currentSignalStrengths = new SparseIntArray();
-
- void setOnBattery(boolean onBattery) {
- this.onBattery = onBattery;
- bi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
- currentTimeMs * 1000);
- }
-
- void setModemActive(boolean active) {
- modemActive = active;
- final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
- : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
- bi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
- }
-
- void setRatType(@Annotation.NetworkType int dataType,
- @BatteryStats.RadioAccessTechnology int rat) {
- currentNetworkDataType = dataType;
- currentRat = rat;
- bi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
- currentFrequencyRange);
- }
-
- void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
- currentFrequencyRange = frequency;
- bi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
- ServiceState.STATE_IN_SERVICE, frequency);
- }
-
- void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
- currentSignalStrengths.put(rat, strength);
- final int size = currentSignalStrengths.size();
- final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
- bi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
- }
- }
- final ModemAndBatteryState state = new ModemAndBatteryState();
+ final ModemAndBatteryState state = new ModemAndBatteryState(bi, null);
IntConsumer incrementTime = inc -> {
state.currentTimeMs += inc;
@@ -1253,6 +1228,7 @@
expectedDurationsMs[currentRat][currentFrequencyRange][currentSignalStrength] += inc;
};
+
state.setOnBattery(false);
state.setModemActive(false);
state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
@@ -1260,95 +1236,367 @@
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// While not on battery, the timers should not increase.
state.setModemActive(true);
incrementTime.accept(100);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
incrementTime.accept(200);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
incrementTime.accept(500);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
incrementTime.accept(300);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
incrementTime.accept(400);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
incrementTime.accept(500);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
// start counting up.
state.setOnBattery(true);
incrementTime.accept(600);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
-
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Changing LTE signal strength should be tracked.
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_POOR);
incrementTime.accept(700);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
incrementTime.accept(800);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_GOOD);
incrementTime.accept(900);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
CellSignalStrength.SIGNAL_STRENGTH_GREAT);
incrementTime.accept(1000);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Change in the signal strength of nonactive RAT should not affect anything.
state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
CellSignalStrength.SIGNAL_STRENGTH_POOR);
incrementTime.accept(1100);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Changing to OTHER Rat should start tracking the poor signal strength.
state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
incrementTime.accept(1200);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Noting frequency change should not affect non NR Rat.
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
incrementTime.accept(1300);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Now the NR Rat, HIGH frequency range, good signal strength should start counting.
state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
incrementTime.accept(1400);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Noting frequency change should not affect non NR Rat.
state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
incrementTime.accept(1500);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
// Modem no longer active, should not be tracking any more.
state.setModemActive(false);
incrementTime.accept(1500);
- checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+ }
+ @SmallTest
+ public void testGetPerStateActiveRadioDurationMs_withModemActivity() {
+ final MockClock clock = new MockClock(); // holds realtime and uptime in ms
+ final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
+ bi.setPowerProfile(mock(PowerProfile.class));
+ final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
+ final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
+ final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
+
+ final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+ final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
+ final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+ for (int rat = 0; rat < ratCount; rat++) {
+ for (int freq = 0; freq < frequencyCount; freq++) {
+ if (rat != RADIO_ACCESS_TECHNOLOGY_NR
+ && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ // Only the NR RAT should have per frequency data.
+ expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
+ } else {
+ expectedRxDurationsMs[rat][freq] = 0;
+ }
+ expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
+
+ for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
+ expectedDurationsMs[rat][freq][txLvl] = 0;
+
+ if (rat != RADIO_ACCESS_TECHNOLOGY_NR
+ && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ // Only the NR RAT should have per frequency data.
+ expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
+ } else {
+ expectedTxDurationsMs[rat][freq][txLvl] = 0;
+ }
+ expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
+ }
+ }
+ }
+
+ final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, new int[txLevelCount], 0L);
+ final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai);
+
+ IntConsumer incrementTime = inc -> {
+ state.currentTimeMs += inc;
+ clock.realtime = clock.uptime = state.currentTimeMs;
+
+ // If the device is not on battery, no timers should increment.
+ if (!state.onBattery) return;
+ // If the modem is not active, no timers should increment.
+ if (!state.modemActive) return;
+
+ final int currRat = state.currentRat;
+ final int currFreqRange =
+ currRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
+ int currSignalStrength = state.currentSignalStrengths.get(currRat);
+
+ expectedDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
+
+ // Evaluate the HAL provided time in states.
+ switch (state.modemState) {
+ case SLEEP:
+ long sleepMs = state.modemActivityInfo.getSleepTimeMillis();
+ state.modemActivityInfo.setSleepTimeMillis(sleepMs + inc);
+ break;
+ case IDLE:
+ long idleMs = state.modemActivityInfo.getIdleTimeMillis();
+ state.modemActivityInfo.setIdleTimeMillis(idleMs + inc);
+ break;
+ case RECEIVING:
+ long rxMs = state.modemActivityInfo.getReceiveTimeMillis();
+ state.modemActivityInfo.setReceiveTimeMillis(rxMs + inc);
+ expectedRxDurationsMs[currRat][currFreqRange] += inc;
+ break;
+ case TRANSMITTING:
+ int[] txMs = state.modemActivityInfo.getTransmitTimeMillis();
+ txMs[currSignalStrength] += inc;
+ state.modemActivityInfo.setTransmitTimeMillis(txMs);
+ expectedTxDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
+ break;
+ }
+ };
+
+ state.setOnBattery(false);
+ state.setModemActive(false);
+ state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+ CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // While not on battery, the timers should not increase.
+ state.setModemActive(true);
+ incrementTime.accept(100);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
+ incrementTime.accept(200);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
+ CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+ incrementTime.accept(500);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
+ incrementTime.accept(300);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
+ incrementTime.accept(400);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
+ incrementTime.accept(500);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Data will now be available.
+ for (int rat = 0; rat < ratCount; rat++) {
+ for (int freq = 0; freq < frequencyCount; freq++) {
+ if (rat == RADIO_ACCESS_TECHNOLOGY_NR
+ || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ // Only the NR RAT should have per frequency data.
+ expectedRxDurationsMs[rat][freq] = 0;
+ }
+ for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
+ if (rat == RADIO_ACCESS_TECHNOLOGY_NR
+ || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ // Only the NR RAT should have per frequency data.
+ expectedTxDurationsMs[rat][freq][txLvl] = 0;
+ }
+ }
+ }
+ }
+
+ // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
+ // start counting up.
+ state.setOnBattery(true);
+ incrementTime.accept(300);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(500);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(600);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+ // Changing LTE signal strength should be tracked.
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_POOR);
+ incrementTime.accept(300);
+ state.setModemState(ModemState.SLEEP);
+ incrementTime.accept(1000);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(700);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ incrementTime.accept(800);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(222);
+ state.setModemState(ModemState.IDLE);
+ incrementTime.accept(111);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(7777);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+ incrementTime.accept(88);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(900);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_GREAT);
+ incrementTime.accept(123);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(333);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(1000);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(555);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Change in the signal strength of nonactive RAT should not affect anything.
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+ CellSignalStrength.SIGNAL_STRENGTH_POOR);
+ incrementTime.accept(631);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(321);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(99);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Changing to OTHER Rat should start tracking the poor signal strength.
+ state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
+ incrementTime.accept(1200);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Noting frequency change should not affect non NR Rat.
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
+ incrementTime.accept(444);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(1300);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Now the NR Rat, HIGH frequency range, good signal strength should start counting.
+ state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
+ incrementTime.accept(1400);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Frequency changed to low.
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
+ incrementTime.accept(852);
+ state.setModemState(ModemState.RECEIVING);
+ incrementTime.accept(157);
+ state.setModemState(ModemState.TRANSMITTING);
+ incrementTime.accept(1500);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
+
+ // Modem no longer active, should not be tracking any more.
+ state.setModemActive(false);
+ incrementTime.accept(1500);
+ state.noteModemControllerActivity();
+ checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+ expectedTxDurationsMs, bi, state.currentTimeMs);
}
private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
@@ -1426,28 +1674,124 @@
}
private void checkPerStateActiveRadioDurations(long[][][] expectedDurationsMs,
+ long[][] expectedRxDurationsMs, long[][][] expectedTxDurationsMs,
BatteryStatsImpl bi, long currentTimeMs) {
for (int rat = 0; rat < expectedDurationsMs.length; rat++) {
final long[][] expectedRatDurationsMs = expectedDurationsMs[rat];
for (int freq = 0; freq < expectedRatDurationsMs.length; freq++) {
+ final long expectedRxDurationMs = expectedRxDurationsMs[rat][freq];
+
+ // Build a verbose fail message, just in case.
+ final StringBuilder rxFailSb = new StringBuilder();
+ rxFailSb.append("Wrong time in Rx state for RAT:");
+ rxFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+ rxFailSb.append(", frequency:");
+ rxFailSb.append(ServiceState.frequencyRangeToString(freq));
+ assertEquals(rxFailSb.toString(), expectedRxDurationMs,
+ bi.getActiveRxRadioDurationMs(rat, freq, currentTimeMs));
+
final long[] expectedFreqDurationsMs = expectedRatDurationsMs[freq];
for (int strength = 0; strength < expectedFreqDurationsMs.length; strength++) {
final long expectedSignalStrengthDurationMs = expectedFreqDurationsMs[strength];
+ final long expectedTxDurationMs = expectedTxDurationsMs[rat][freq][strength];
final long actualDurationMs = bi.getActiveRadioDurationMs(rat, freq,
strength, currentTimeMs);
- // Build a verbose fail message, just in case.
- final StringBuilder sb = new StringBuilder();
- sb.append("Wrong time in state for RAT:");
- sb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
- sb.append(", frequency:");
- sb.append(ServiceState.frequencyRangeToString(freq));
- sb.append(", strength:");
- sb.append(strength);
+ final StringBuilder failSb = new StringBuilder();
+ failSb.append("Wrong time in state for RAT:");
+ failSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+ failSb.append(", frequency:");
+ failSb.append(ServiceState.frequencyRangeToString(freq));
+ failSb.append(", strength:");
+ failSb.append(strength);
+ assertEquals(failSb.toString(), expectedSignalStrengthDurationMs,
+ actualDurationMs);
- assertEquals(sb.toString(), expectedSignalStrengthDurationMs, actualDurationMs);
+ final StringBuilder txFailSb = new StringBuilder();
+ txFailSb.append("Wrong time in Tx state for RAT:");
+ txFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+ txFailSb.append(", frequency:");
+ txFailSb.append(ServiceState.frequencyRangeToString(freq));
+ txFailSb.append(", strength:");
+ txFailSb.append(strength);
+ assertEquals(txFailSb.toString(), expectedTxDurationMs,
+ bi.getActiveTxRadioDurationMs(rat, freq, strength, currentTimeMs));
}
}
}
}
+
+ private class ModemAndBatteryState {
+ public long currentTimeMs = 100;
+ public boolean onBattery = false;
+ public boolean modemActive = false;
+ @Annotation.NetworkType
+ public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ @BatteryStats.RadioAccessTechnology
+ public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+ @ServiceState.FrequencyRange
+ public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ public SparseIntArray currentSignalStrengths = new SparseIntArray();
+ public ModemState modemState = ModemState.SLEEP;
+ public ModemActivityInfo modemActivityInfo;
+
+ private final MockBatteryStatsImpl mBsi;
+
+ ModemAndBatteryState(MockBatteryStatsImpl bsi, ModemActivityInfo mai) {
+ mBsi = bsi;
+ modemActivityInfo = mai;
+ }
+
+ void setOnBattery(boolean onBattery) {
+ this.onBattery = onBattery;
+ mBsi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
+ currentTimeMs * 1000);
+ mBsi.setOnBatteryInternal(onBattery);
+ noteModemControllerActivity();
+ }
+
+ void setModemActive(boolean active) {
+ modemActive = active;
+ final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
+ : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
+ mBsi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
+ noteModemControllerActivity();
+ }
+
+ void setRatType(@Annotation.NetworkType int dataType,
+ @BatteryStats.RadioAccessTechnology int rat) {
+ currentNetworkDataType = dataType;
+ currentRat = rat;
+ mBsi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
+ currentFrequencyRange);
+ }
+
+ void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
+ currentFrequencyRange = frequency;
+ mBsi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
+ ServiceState.STATE_IN_SERVICE, frequency);
+ }
+
+ void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
+ currentSignalStrengths.put(rat, strength);
+ final int size = currentSignalStrengths.size();
+ final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
+ mBsi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
+ }
+
+ void setModemState(ModemState state) {
+ modemState = state;
+ }
+
+ void noteModemControllerActivity() {
+ if (modemActivityInfo == null) return;
+ modemActivityInfo.setTimestamp(currentTimeMs);
+ ModemActivityInfo copy = new ModemActivityInfo(modemActivityInfo.getTimestampMillis(),
+ modemActivityInfo.getSleepTimeMillis(), modemActivityInfo.getIdleTimeMillis(),
+ modemActivityInfo.getTransmitTimeMillis().clone(),
+ modemActivityInfo.getReceiveTimeMillis());
+ mBsi.noteModemControllerActivity(copy, POWER_DATA_UNAVAILABLE,
+ currentTimeMs, currentTimeMs, mNetworkStatsManager);
+ }
+ }
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c3b0017..3e91eed 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -452,6 +452,7 @@
<permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
<permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
<permission name="android.permission.NEARBY_WIFI_DEVICES" />
+ <permission name="android.permission.MANAGE_WIFI_INTERFACES" />
<permission name="android.permission.OVERRIDE_WIFI_CONFIG" />
<!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. -->
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index df2b2a3..e898f57 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1309,6 +1309,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-711194343": {
+ "message": "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"-706481945": {
"message": "TaskFragment parent info changed name=%s parentTaskId=%d",
"level": "VERBOSE",
@@ -2587,6 +2593,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "599897753": {
+ "message": "Previous Activity is %s. Back type is %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"600140673": {
"message": "checkBootAnimationComplete: Waiting for anim complete",
"level": "INFO",
@@ -2671,12 +2683,6 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "664667685": {
- "message": "Activity %s: enableOnBackInvokedCallback=false. Returning null BackNavigationInfo.",
- "level": "DEBUG",
- "group": "WM_DEBUG_BACK_PREVIEW",
- "at": "com\/android\/server\/wm\/BackNavigationController.java"
- },
"665256544": {
"message": "All windows drawn!",
"level": "DEBUG",
@@ -2887,6 +2893,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/TaskFragment.java"
},
+ "948208142": {
+ "message": "Setting Activity.mLauncherTaskBehind to true. Activity=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"950074526": {
"message": "setLockTaskMode: Can't lock due to auth",
"level": "WARN",
@@ -3103,6 +3115,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
+ "1172542963": {
+ "message": "onBackNavigationDone backType=%s, task=%s, prevTaskTopActivity=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"1178653181": {
"message": "Old wallpaper still the target.",
"level": "VERBOSE",
@@ -3415,11 +3433,11 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
- "1554795024": {
- "message": "Previous Activity is %s",
+ "1544805551": {
+ "message": "Skipping app transition animation. task=%s",
"level": "DEBUG",
"group": "WM_DEBUG_BACK_PREVIEW",
- "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ "at": "com\/android\/server\/wm\/Task.java"
},
"1557732761": {
"message": "For Intent %s bringing to top: %s",
diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java
index cffdf28..d083e44 100644
--- a/graphics/java/android/graphics/text/LineBreakConfig.java
+++ b/graphics/java/android/graphics/text/LineBreakConfig.java
@@ -26,7 +26,7 @@
/**
* Indicates the strategies can be used when calculating the text wrapping.
*
- * See <a href="https://drafts.csswg.org/css-text/#line-break-property">the line-break property</a>
+ * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">the line-break property</a>
*/
public final class LineBreakConfig {
@@ -78,21 +78,87 @@
@Retention(RetentionPolicy.SOURCE)
public @interface LineBreakWordStyle {}
- private @LineBreakStyle int mLineBreakStyle = LINE_BREAK_STYLE_NONE;
- private @LineBreakWordStyle int mLineBreakWordStyle = LINE_BREAK_WORD_STYLE_NONE;
+ /**
+ * A builder for creating {@link LineBreakConfig}.
+ */
+ public static final class Builder {
+ // The line break style for the LineBreakConfig.
+ private @LineBreakStyle int mLineBreakStyle = LineBreakConfig.LINE_BREAK_STYLE_NONE;
- public LineBreakConfig() {
+ // The line break word style for the LineBreakConfig.
+ private @LineBreakWordStyle int mLineBreakWordStyle =
+ LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE;
+
+ /**
+ * Builder constructor with line break parameters.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Set the line break style.
+ *
+ * @param lineBreakStyle the new line break style.
+ * @return this Builder
+ */
+ public @NonNull Builder setLineBreakStyle(@LineBreakStyle int lineBreakStyle) {
+ mLineBreakStyle = lineBreakStyle;
+ return this;
+ }
+
+ /**
+ * Set the line break word style.
+ *
+ * @param lineBreakWordStyle the new line break word style.
+ * @return this Builder
+ */
+ public @NonNull Builder setLineBreakWordStyle(@LineBreakWordStyle int lineBreakWordStyle) {
+ mLineBreakWordStyle = lineBreakWordStyle;
+ return this;
+ }
+
+ /**
+ * Build the {@link LineBreakConfig}
+ *
+ * @return the LineBreakConfig instance.
+ */
+ public @NonNull LineBreakConfig build() {
+ return new LineBreakConfig(mLineBreakStyle, mLineBreakWordStyle);
+ }
}
/**
- * Set the line break configuration.
+ * Create the LineBreakConfig instance.
*
- * @param lineBreakConfig the new line break configuration.
+ * @param lineBreakStyle the line break style for text wrapping.
+ * @param lineBreakWordStyle the line break word style for text wrapping.
+ * @return the {@link LineBreakConfig} instance.
+ * @hide
*/
- public void set(@NonNull LineBreakConfig lineBreakConfig) {
- Objects.requireNonNull(lineBreakConfig);
- mLineBreakStyle = lineBreakConfig.getLineBreakStyle();
- mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle();
+ public static @NonNull LineBreakConfig getLineBreakConfig(@LineBreakStyle int lineBreakStyle,
+ @LineBreakWordStyle int lineBreakWordStyle) {
+ LineBreakConfig.Builder builder = new LineBreakConfig.Builder();
+ return builder.setLineBreakStyle(lineBreakStyle)
+ .setLineBreakWordStyle(lineBreakWordStyle)
+ .build();
+ }
+
+ /** @hide */
+ public static final LineBreakConfig NONE =
+ new Builder().setLineBreakStyle(LINE_BREAK_STYLE_NONE)
+ .setLineBreakWordStyle(LINE_BREAK_WORD_STYLE_NONE).build();
+
+ private final @LineBreakStyle int mLineBreakStyle;
+ private final @LineBreakWordStyle int mLineBreakWordStyle;
+
+ /**
+ * Constructor with the line break parameters.
+ * Use the {@link LineBreakConfig.Builder} to create the LineBreakConfig instance.
+ */
+ private LineBreakConfig(@LineBreakStyle int lineBreakStyle,
+ @LineBreakWordStyle int lineBreakWordStyle) {
+ mLineBreakStyle = lineBreakStyle;
+ mLineBreakWordStyle = lineBreakWordStyle;
}
/**
@@ -105,15 +171,6 @@
}
/**
- * Set the line break style.
- *
- * @param lineBreakStyle the new line break style.
- */
- public void setLineBreakStyle(@LineBreakStyle int lineBreakStyle) {
- mLineBreakStyle = lineBreakStyle;
- }
-
- /**
* Get the line break word style.
*
* @return The current line break word style to be used for the text wrapping.
@@ -122,15 +179,6 @@
return mLineBreakWordStyle;
}
- /**
- * Set the line break word style.
- *
- * @param lineBreakWordStyle the new line break word style.
- */
- public void setLineBreakWordStyle(@LineBreakWordStyle int lineBreakWordStyle) {
- mLineBreakWordStyle = lineBreakWordStyle;
- }
-
@Override
public boolean equals(Object o) {
if (o == null) return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 8d5fdfb..08cb252 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -52,14 +52,17 @@
*/
public class BackAnimationController implements RemoteCallable<BackAnimationController> {
- private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
- public static final boolean IS_ENABLED = SystemProperties
- .getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
private static final String BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP =
"persist.debug.back_predictability_progress_threshold";
+ // By default, enable new back dispatching without any animations.
+ private static final int BACK_PREDICTABILITY_PROP =
+ SystemProperties.getInt("persist.debug.back_predictability", 1);
+ public static final boolean IS_ENABLED = BACK_PREDICTABILITY_PROP > 0;
private static final int PROGRESS_THRESHOLD = SystemProperties
.getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1);
private static final String TAG = "BackAnimationController";
+ @VisibleForTesting
+ boolean mEnableAnimations = (BACK_PREDICTABILITY_PROP & (1 << 1)) != 0;
/**
* Location of the initial touch event of the back gesture.
@@ -255,7 +258,7 @@
backNavigationInfo.getTaskWindowConfiguration());
}
mTransaction.apply();
- } else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
+ } else if (shouldDispatchToLauncher(backType)) {
targetCallback = mBackToLauncherCallback;
} else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
@@ -309,7 +312,7 @@
BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget);
IOnBackInvokedCallback targetCallback = null;
- if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
+ if (shouldDispatchToLauncher(backType)) {
targetCallback = mBackToLauncherCallback;
} else if (backType == BackNavigationInfo.TYPE_CROSS_TASK
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
@@ -330,8 +333,7 @@
return;
}
int backType = mBackNavigationInfo.getType();
- boolean shouldDispatchToLauncher = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
- && mBackToLauncherCallback != null;
+ boolean shouldDispatchToLauncher = shouldDispatchToLauncher(backType);
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
? mBackToLauncherCallback
: mBackNavigationInfo.getOnBackInvokedCallback();
@@ -356,6 +358,17 @@
}
}
+ private boolean shouldDispatchToLauncher(int backType) {
+ return backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
+ && mBackToLauncherCallback != null
+ && mEnableAnimations;
+ }
+
+ @VisibleForTesting
+ void setEnableAnimations(boolean shouldEnable) {
+ mEnableAnimations = shouldEnable;
+ }
+
private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) {
if (callback == null) {
return;
@@ -468,7 +481,7 @@
return;
}
RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget();
- if (animationTarget != null && mTriggerBack) {
+ if (animationTarget != null) {
if (animationTarget.leash != null && animationTarget.leash.isValid()) {
mTransaction.remove(animationTarget.leash);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 51067a4..4583389 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -344,7 +344,7 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration newMergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {}
+ boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {}
@Override
public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index b52c8d1..5246117 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -98,6 +98,7 @@
private WindowContainerToken mWinToken2;
private int mDividePosition;
private boolean mInitialized = false;
+ private boolean mFreezeDividerWindow = false;
private int mOrientation;
private int mRotation;
@@ -225,11 +226,6 @@
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
initDividerPosition(mTempRect);
- if (mInitialized) {
- release();
- init();
- }
-
return true;
}
@@ -298,20 +294,37 @@
}
/** Releases the surface holding the current {@link DividerView}. */
- public void release() {
+ public void release(SurfaceControl.Transaction t) {
if (!mInitialized) return;
mInitialized = false;
- mSplitWindowManager.release();
+ mSplitWindowManager.release(t);
mDisplayImeController.removePositionProcessor(mImePositionProcessor);
mImePositionProcessor.reset();
}
+ public void release() {
+ release(null /* t */);
+ }
+
+ /** Releases and re-inflates {@link DividerView} on the root surface. */
+ public void update(SurfaceControl.Transaction t) {
+ if (!mInitialized) return;
+ mSplitWindowManager.release(t);
+ mImePositionProcessor.reset();
+ mSplitWindowManager.init(this, mInsetsState);
+ }
+
@Override
public void insetsChanged(InsetsState insetsState) {
mInsetsState.set(insetsState);
if (!mInitialized) {
return;
}
+ if (mFreezeDividerWindow) {
+ // DO NOT change its layout before transition actually run because it might cause
+ // flicker.
+ return;
+ }
mSplitWindowManager.onInsetsChanged(insetsState);
}
@@ -323,6 +336,10 @@
}
}
+ public void setFreezeDividerWindow(boolean freezeDividerWindow) {
+ mFreezeDividerWindow = freezeDividerWindow;
+ }
+
/**
* Updates bounds with the passing position. Usually used to update recording bounds while
* performing animation or dragging divider bar to resize the splits.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 4903f9d..833d9d5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -58,6 +58,9 @@
private SurfaceControl mLeash;
private DividerView mDividerView;
+ // Used to "pass" a transaction to WWM.remove so that view removal can be synchronized.
+ private SurfaceControl.Transaction mSyncTransaction = null;
+
public interface ParentContainerCallbacks {
void attachToParentSurface(SurfaceControl.Builder b);
void onLeashReady(SurfaceControl leash);
@@ -130,22 +133,38 @@
* Releases the surface control of the current {@link DividerView} and tear down the view
* hierarchy.
*/
- void release() {
+ void release(@Nullable SurfaceControl.Transaction t) {
if (mDividerView != null) {
mDividerView = null;
}
if (mViewHost != null){
+ mSyncTransaction = t;
mViewHost.release();
+ mSyncTransaction = null;
mViewHost = null;
}
if (mLeash != null) {
- new SurfaceControl.Transaction().remove(mLeash).apply();
+ if (t == null) {
+ new SurfaceControl.Transaction().remove(mLeash).apply();
+ } else {
+ t.remove(mLeash);
+ }
mLeash = null;
}
}
+ @Override
+ protected void removeSurface(SurfaceControl sc) {
+ // This gets called via SurfaceControlViewHost.release()
+ if (mSyncTransaction != null) {
+ mSyncTransaction.remove(sc);
+ } else {
+ super.removeSurface(sc);
+ }
+ }
+
void setInteractive(boolean interactive) {
if (mDividerView == null) return;
mDividerView.setInteractive(interactive);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
index 3115f8a..11633a9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
@@ -253,11 +253,11 @@
private WindowManager.LayoutParams getDismissTargetLayoutParams() {
final Point windowSize = new Point();
mWindowManager.getDefaultDisplay().getRealSize(windowSize);
-
+ int height = Math.min(windowSize.y, mDismissAreaHeight);
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
- mDismissAreaHeight,
- 0, windowSize.y - mDismissAreaHeight,
+ height,
+ 0, windowSize.y - height,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 48dd1fe..ec1ddf0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -29,6 +29,7 @@
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -1171,6 +1172,8 @@
updateUnfoldBounds();
return;
}
+
+ mSplitLayout.update(null /* t */);
onLayoutSizeChanged(mSplitLayout);
}
}
@@ -1198,7 +1201,6 @@
if (!ENABLE_SHELL_TRANSITIONS) return;
final SurfaceControl.Transaction t = mTransactionPool.acquire();
- setDividerVisibility(false, t);
mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
mSplitLayout.rotateTo(toRotation, mDisplayLayout.stableInsets());
updateWindowBounds(mSplitLayout, wct);
@@ -1255,8 +1257,15 @@
@Nullable TransitionRequestInfo request) {
final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
if (triggerTask == null) {
- // Still want to monitor everything while in split-screen, so return non-null.
- return mMainStage.isActive() ? new WindowContainerTransaction() : null;
+ if (mMainStage.isActive()) {
+ if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null) {
+ mSplitLayout.setFreezeDividerWindow(true);
+ }
+ // Still want to monitor everything while in split-screen, so return non-null.
+ return new WindowContainerTransaction();
+ } else {
+ return null;
+ }
} else if (triggerTask.displayId != mDisplayId) {
// Skip handling task on the other display.
return null;
@@ -1352,8 +1361,14 @@
// If we're not in split-mode, just abort so something else can handle it.
if (!mMainStage.isActive()) return false;
+ mSplitLayout.setFreezeDividerWindow(false);
for (int iC = 0; iC < info.getChanges().size(); ++iC) {
final TransitionInfo.Change change = info.getChanges().get(iC);
+ if (change.getMode() == TRANSIT_CHANGE
+ && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
+ mSplitLayout.update(startTransaction);
+ }
+
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
if (taskInfo == null || !taskInfo.hasParentTask()) continue;
final StageTaskListener stage = getStageOfTask(taskInfo);
@@ -1368,10 +1383,6 @@
Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
+ " with " + taskInfo.taskId + " before startAnimation().");
}
- } else if (info.getType() == TRANSIT_CHANGE
- && change.getStartRotation() != change.getEndRotation()) {
- // Show the divider after transition finished.
- setDividerVisibility(true, finishTransaction);
}
}
if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index 1bef552e..49f907b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -62,6 +62,7 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.HardwareBuffer;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Trace;
@@ -243,7 +244,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "TaskSnapshot#relayout");
session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0,
tmpFrames, tmpMergedConfiguration, surfaceControl, tmpInsetsState,
- tmpControls);
+ tmpControls, new Bundle());
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} catch (RemoteException e) {
snapshotSurface.clearWindowSynced();
@@ -517,7 +518,7 @@
private void reportDrawn() {
try {
- mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+ mSession.finishDrawing(mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE);
} catch (RemoteException e) {
clearWindowSynced();
}
@@ -534,7 +535,7 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
+ boolean alwaysConsumeSystemBars, int displayId, int seqId) {
if (mOuter != null) {
mOuter.mSplashScreenExecutor.execute(() -> {
if (mergedConfiguration != null
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 9054685..3e7ee25 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -78,6 +78,7 @@
MockitoAnnotations.initMocks(this);
mController = new BackAnimationController(
mShellExecutor, mTransaction, mActivityTaskManager, mContext);
+ mController.setEnableAnimations(true);
}
private void createNavigationInfo(RemoteAnimationTarget topAnimationTarget,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
index 9bb54a1..2e5078d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -61,7 +61,7 @@
public void testInitRelease() {
mSplitWindowManager.init(mSplitLayout, new InsetsState());
assertThat(mSplitWindowManager.getSurfaceControl()).isNotNull();
- mSplitWindowManager.release();
+ mSplitWindowManager.release(null /* t */);
assertThat(mSplitWindowManager.getSurfaceControl()).isNull();
}
}
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 63b831d..c80fb18 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -118,7 +118,7 @@
"libz",
],
},
- linux_glibc: {
+ host_linux: {
srcs: [
"CursorWindow.cpp",
],
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index 055dbb2..99508a2 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -48,8 +48,6 @@
TRANSACTION_isObbMounted,
TRANSACTION_getMountedObbPath,
TRANSACTION_isExternalStorageEmulated,
- TRANSACTION_decryptStorage,
- TRANSACTION_encryptStorage,
};
class BpMountService: public BpInterface<IMountService>
@@ -517,40 +515,6 @@
path = reply.readString16();
return true;
}
-
- int32_t decryptStorage(const String16& password)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
- data.writeString16(password);
- if (remote()->transact(TRANSACTION_decryptStorage, data, &reply) != NO_ERROR) {
- ALOGD("decryptStorage could not contact remote\n");
- return -1;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("decryptStorage caught exception %d\n", err);
- return err;
- }
- return reply.readInt32();
- }
-
- int32_t encryptStorage(const String16& password)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
- data.writeString16(password);
- if (remote()->transact(TRANSACTION_encryptStorage, data, &reply) != NO_ERROR) {
- ALOGD("encryptStorage could not contact remote\n");
- return -1;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("encryptStorage caught exception %d\n", err);
- return err;
- }
- return reply.readInt32();
- }
};
IMPLEMENT_META_INTERFACE(MountService, "android.os.storage.IStorageManager")
diff --git a/libs/storage/include/storage/IMountService.h b/libs/storage/include/storage/IMountService.h
index 5b07318..5a9c39b 100644
--- a/libs/storage/include/storage/IMountService.h
+++ b/libs/storage/include/storage/IMountService.h
@@ -70,8 +70,6 @@
const sp<IObbActionListener>& token, const int32_t nonce) = 0;
virtual bool isObbMounted(const String16& filename) = 0;
virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
- virtual int32_t decryptStorage(const String16& password) = 0;
- virtual int32_t encryptStorage(const String16& password) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml
index 3fb3fd4..5c90fd0 100644
--- a/packages/BackupRestoreConfirmation/res/values/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values/strings.xml
@@ -44,8 +44,6 @@
<string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string>
<!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. -->
<string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
- <!-- Text for message to user that they must supply an encryption password to use for a full backup operation because their phone is locked. -->
- <string name="backup_enc_password_required">Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:</string>
<!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. -->
<string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index d6b6bf8..3c790f0 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -27,8 +27,6 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.storage.IStorageManager;
-import android.os.storage.StorageManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Slog;
@@ -66,10 +64,8 @@
Handler mHandler;
IBackupManager mBackupManager;
- IStorageManager mStorageManager;
FullObserver mObserver;
int mToken;
- boolean mIsEncrypted;
boolean mDidAcknowledge;
String mAction;
@@ -144,7 +140,6 @@
}
mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
- mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
mHandler = new ObserverHandler(getApplicationContext());
final Object oldObserver = getLastNonConfigurationInstance();
@@ -248,20 +243,13 @@
mDenyButton.setEnabled(!mDidAcknowledge);
}
- // We vary the password prompt depending on whether one is predefined, and whether
- // the device is encrypted.
- mIsEncrypted = deviceIsEncrypted();
+ // We vary the password prompt depending on whether one is predefined.
if (!haveBackupPassword()) {
curPwDesc.setVisibility(View.GONE);
mCurPassword.setVisibility(View.GONE);
if (layoutId == R.layout.confirm_backup) {
TextView encPwDesc = findViewById(R.id.enc_password_desc);
- if (mIsEncrypted) {
- encPwDesc.setText(R.string.backup_enc_password_required);
- monitorEncryptionPassword();
- } else {
- encPwDesc.setText(R.string.backup_enc_password_optional);
- }
+ encPwDesc.setText(R.string.backup_enc_password_optional);
}
}
}
@@ -312,20 +300,6 @@
}
}
- boolean deviceIsEncrypted() {
- try {
- return mStorageManager.getEncryptionState()
- != StorageManager.ENCRYPTION_STATE_NONE
- && mStorageManager.getPasswordType()
- != StorageManager.CRYPT_TYPE_DEFAULT;
- } catch (Exception e) {
- // If we can't talk to the storagemanager service we have a serious problem; fail
- // "secure" i.e. assuming that the device is encrypted.
- Slog.e(TAG, "Unable to communicate with storagemanager service: " + e.getMessage());
- return true;
- }
- }
-
boolean haveBackupPassword() {
try {
return mBackupManager.hasBackupPassword();
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
index f681ba1..06f2a62 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
@@ -327,16 +327,11 @@
* @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is
* for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only
* counting iface stats.
- * @param set usage state of this {@link Entry}. Should be one of the following
- * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
+ * @param set usage state of this {@link Entry}.
* @param tag tag of this {@link Entry}.
- * @param metered metered state of this {@link Entry}. Should be one of the following
- * values: {link #METERED_YES}, {link #METERED_NO}.
- * @param roaming roaming state of this {@link Entry}. Should be one of the following
- * values: {link #ROAMING_YES}, {link #ROAMING_NO}.
- * @param defaultNetwork default network status of this {@link Entry}. Should be one
- * of the following values: {link #DEFAULT_NETWORK_YES},
- * {link #DEFAULT_NETWORK_NO}.
+ * @param metered metered state of this {@link Entry}.
+ * @param roaming roaming state of this {@link Entry}.
+ * @param defaultNetwork default network status of this {@link Entry}.
* @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
* represent the contents of IP packets, including IP headers.
* @param rxPackets Number of packets received for this {@link Entry}. Statistics should
@@ -401,8 +396,7 @@
}
/**
- * @return the set state of this entry. Should be one of the following
- * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
+ * @return the set state of this entry.
*/
@State public int getSet() {
return set;
@@ -416,24 +410,21 @@
}
/**
- * @return the metered state. Should be one of the following
- * values: {link #METERED_YES}, {link #METERED_NO}.
+ * @return the metered state.
*/
@Meteredness public int getMetered() {
return metered;
}
/**
- * @return the roaming state. Should be one of the following
- * values: {link #ROAMING_YES}, {link #ROAMING_NO}.
+ * @return the roaming state.
*/
@Roaming public int getRoaming() {
return roaming;
}
/**
- * @return the default network state. Should be one of the following
- * values: {link #DEFAULT_NETWORK_YES}, {link #DEFAULT_NETWORK_NO}.
+ * @return the default network state.
*/
@DefaultNetwork public int getDefaultNetwork() {
return defaultNetwork;
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index e7765e6..e93371d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -536,6 +536,7 @@
<uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
<uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
+ <uses-permission android:name="android.permission.MANAGE_WIFI_INTERFACES" />
<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
P2P external approver API sets require MANAGE_WIFI_NETWORK_SELECTION permission. -->
diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml
index 91d81a2..cb63300 100644
--- a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml
@@ -19,6 +19,7 @@
android:id="@+id/date_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/dream_overlay_complication_shadow_padding"
android:gravity="center_horizontal"
android:textColor="@android:color/white"
android:shadowColor="@color/keyguard_shadow_color"
diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml
index 3900ea5..76fe58c 100644
--- a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml
@@ -19,6 +19,7 @@
android:id="@+id/weather_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingHorizontal="@dimen/dream_overlay_complication_shadow_padding"
android:textColor="@android:color/white"
android:shadowColor="@color/keyguard_shadow_color"
android:shadowRadius="?attr/shadowRadius"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 52ec516..ffae601 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1376,6 +1376,7 @@
<dimen name="dream_overlay_complication_weather_text_size">18sp</dimen>
<dimen name="dream_overlay_complication_preview_text_size">36sp</dimen>
<dimen name="dream_overlay_complication_preview_icon_padding">28dp</dimen>
+ <dimen name="dream_overlay_complication_shadow_padding">2dp</dimen>
<!-- The position of the end guide, which dream overlay complications can align their start with
if their end is aligned with the parent end. Represented as the percentage over from the
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1ef6dea..3858f9c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -326,7 +326,6 @@
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private final Executor mBackgroundExecutor;
private SensorPrivacyManager mSensorPrivacyManager;
- private int mFaceAuthUserId;
/**
* Short delay before restarting fingerprint authentication after a successful try. This should
@@ -1030,8 +1029,8 @@
boolean cameraPrivacyEnabled = false;
if (mSensorPrivacyManager != null) {
cameraPrivacyEnabled = mSensorPrivacyManager
- .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA,
- mFaceAuthUserId);
+ .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+ SensorPrivacyManager.Sensors.CAMERA);
}
if (msgId == FaceManager.FACE_ERROR_CANCELED
@@ -2599,7 +2598,6 @@
// This would need to be updated for multi-sensor devices
final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
&& mFaceSensorProperties.get(0).supportsFaceDetection;
- mFaceAuthUserId = userId;
if (isEncryptedOrLockdown(userId) && supportsFaceDetection) {
mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
index 4b86862..498e715 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
@@ -119,9 +119,13 @@
if (useInvertedAlphaColor) {
canvas.drawColor(bgColor)
}
+
+ // We may clear the color(if useInvertedAlphaColor is true) of the rounded corner rects
+ // before drawing rounded corners. If the cutout happens to be inside one of these rects, it
+ // will be cleared, so we have to draw rounded corners before cutout.
+ drawRoundedCorners(canvas)
// Cutouts are drawn in DisplayCutoutBaseView.onDraw()
super.onDraw(canvas)
- drawRoundedCorners(canvas)
debugTransparentRegionPaint?.let {
calculateTransparentRect()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c01d2c3..736e2e0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1706,14 +1706,6 @@
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
return;
}
-
- if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
- if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
- // Without this, settings is not enabled until the lock screen first appears
- setShowingLocked(false);
- hideLocked();
- return;
- }
}
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 086cca1..ec6094d 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -47,7 +47,6 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
-import static com.android.systemui.shared.system.QuickStepContract.isGesturalMode;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
@@ -62,6 +61,7 @@
import android.app.IActivityTaskManager;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -107,15 +107,13 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.internal.view.AppearanceRegion;
-import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
+import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener;
import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
-import com.android.systemui.navigationbar.buttons.DeadZone;
import com.android.systemui.navigationbar.buttons.KeyButtonView;
import com.android.systemui.navigationbar.buttons.RotationContextButton;
import com.android.systemui.navigationbar.gestural.QuickswitchOrientedNavHandle;
@@ -127,7 +125,6 @@
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -149,15 +146,15 @@
import java.util.Optional;
import java.util.function.Consumer;
+import javax.inject.Inject;
+
import dagger.Lazy;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
/**
* Contains logic for a navigation bar view.
*/
-public class NavigationBar implements View.OnAttachStateChangeListener, Callbacks {
+public class NavigationBar implements View.OnAttachStateChangeListener,
+ Callbacks, NavigationModeController.ModeChangedListener {
public static final String TAG = "NavigationBar";
private static final boolean DEBUG = false;
@@ -184,6 +181,7 @@
private final NotificationRemoteInputManager mNotificationRemoteInputManager;
private final OverviewProxyService mOverviewProxyService;
private final NavigationModeController mNavigationModeController;
+ private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
private final BroadcastDispatcher mBroadcastDispatcher;
private final CommandQueue mCommandQueue;
private final Optional<Pip> mPipOptional;
@@ -202,7 +200,8 @@
private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
private int mNavigationIconHints = 0;
- private @TransitionMode int mTransitionMode;
+ private @TransitionMode int mNavigationBarMode;
+ private ContentResolver mContentResolver;
private boolean mLongPressHomeEnabled;
private int mDisabledFlags1;
@@ -256,8 +255,7 @@
private int mCurrentRotation;
private ViewTreeObserver.OnGlobalLayoutListener mOrientationHandleGlobalLayoutListener;
private boolean mShowOrientedHandleForImmersiveMode;
- private DeadZone mDeadZone;
- private boolean mImeVisible;
+
@com.android.internal.annotations.VisibleForTesting
public enum NavBarActionEvent implements UiEventLogger.UiEventEnum {
@@ -473,9 +471,7 @@
}
};
- @AssistedInject
- NavigationBar(
- @Assisted Context context,
+ private NavigationBar(Context context,
WindowManager windowManager,
Lazy<AssistManager> assistManagerLazy,
AccessibilityManager accessibilityManager,
@@ -483,6 +479,7 @@
MetricsLogger metricsLogger,
OverviewProxyService overviewProxyService,
NavigationModeController navigationModeController,
+ AccessibilityButtonModeObserver accessibilityButtonModeObserver,
StatusBarStateController statusBarStateController,
SysUiState sysUiFlagsContainer,
BroadcastDispatcher broadcastDispatcher,
@@ -517,6 +514,7 @@
mNotificationRemoteInputManager = notificationRemoteInputManager;
mOverviewProxyService = overviewProxyService;
mNavigationModeController = navigationModeController;
+ mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
mBroadcastDispatcher = broadcastDispatcher;
mCommandQueue = commandQueue;
mPipOptional = pipOptional;
@@ -534,7 +532,7 @@
mTelecomManagerOptional = telecomManagerOptional;
mInputMethodManager = inputMethodManager;
- mNavBarMode = mNavigationModeController.addListener(mModeChangedListener);
+ mNavBarMode = mNavigationModeController.addListener(this);
}
public NavigationBarView getView() {
@@ -548,11 +546,6 @@
R.layout.navigation_bar, mFrame);
barView.addOnAttachStateChangeListener(this);
mNavigationBarView = barView.findViewById(R.id.navigation_bar_view);
- mDeadZone = new DeadZone(mNavigationBarView);
- mNavigationBarView.setTouchHandler(mTouchHandler);
- mNavigationBarView.setNavBarMode(mNavBarMode);
-
- mNavigationBarView.updateRotationButton();
mNavigationBarView.setVisibility(initialVisibility ? View.VISIBLE : View.INVISIBLE);
@@ -565,6 +558,7 @@
mCommandQueue.addCallback(this);
mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled();
+ mContentResolver = mContext.getContentResolver();
mNavBarHelper.init();
mAllowForceNavBarHandleOpaque = mContext.getResources().getBoolean(
R.bool.allow_force_nav_bar_handle_opaque);
@@ -603,7 +597,7 @@
setAutoHideController(/* autoHideController */ null);
mCommandQueue.removeCallback(this);
mWindowManager.removeViewImmediate(mNavigationBarView.getRootView());
- mNavigationModeController.removeListener(mModeChangedListener);
+ mNavigationModeController.removeListener(this);
mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
mNavBarHelper.destroy();
@@ -618,16 +612,15 @@
final Display display = v.getDisplay();
mNavigationBarView.setComponents(mRecentsOptional);
mNavigationBarView.setComponents(mCentralSurfacesOptionalLazy.get().get().getPanelController());
- mNavigationBarView.setDisabledFlags(mDisabledFlags1, mSysUiFlagsContainer);
+ mNavigationBarView.setDisabledFlags(mDisabledFlags1);
mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged);
mNavigationBarView.setOnTouchListener(this::onNavigationTouch);
if (mSavedState != null) {
mNavigationBarView.getLightTransitionsController().restoreState(mSavedState);
}
- setNavigationIconHints(mNavigationIconHints);
+ mNavigationBarView.setNavigationIconHints(mNavigationIconHints);
mNavigationBarView.setWindowVisible(isNavBarWindowVisible());
mNavigationBarView.setBehavior(mBehavior);
- mNavigationBarView.setNavBarMode(mNavBarMode);
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
@@ -872,8 +865,8 @@
pw.println(" mLongPressHomeEnabled=" + mLongPressHomeEnabled);
pw.println(" mNavigationBarWindowState="
+ windowStateToString(mNavigationBarWindowState));
- pw.println(" mTransitionMode="
- + BarTransitions.modeToString(mTransitionMode));
+ pw.println(" mNavigationBarMode="
+ + BarTransitions.modeToString(mNavigationBarMode));
pw.println(" mTransientShown=" + mTransientShown);
pw.println(" mTransientShownFromGestureOnSystemBar="
+ mTransientShownFromGestureOnSystemBar);
@@ -895,7 +888,11 @@
imeShown, showImeSwitcher);
if (hints == mNavigationIconHints) return;
- setNavigationIconHints(hints);
+ mNavigationIconHints = hints;
+ if (!isTablet(mContext)) {
+ // All IME functions handled by launcher via Sysui flags for large screen
+ mNavigationBarView.setNavigationIconHints(hints);
+ }
checkBarModes();
updateSystemUiStateFlags();
}
@@ -955,15 +952,15 @@
/** Restores the appearance and the transient saved state to {@link NavigationBar}. */
public void restoreAppearanceAndTransientState() {
- final int transitionMode = transitionMode(mTransientShown, mAppearance);
- mTransitionMode = transitionMode;
+ final int barMode = barMode(mTransientShown, mAppearance);
+ mNavigationBarMode = barMode;
checkNavBarModes();
if (mAutoHideController != null) {
mAutoHideController.touchAutoHide();
}
if (mLightBarController != null) {
mLightBarController.onNavigationBarAppearanceChanged(mAppearance,
- true /* nbModeChanged */, transitionMode, false /* navbarColorManagedByIme */);
+ true /* nbModeChanged */, barMode, false /* navbarColorManagedByIme */);
}
}
@@ -977,11 +974,11 @@
boolean nbModeChanged = false;
if (mAppearance != appearance) {
mAppearance = appearance;
- nbModeChanged = updateTransitionMode(transitionMode(mTransientShown, appearance));
+ nbModeChanged = updateBarMode(barMode(mTransientShown, appearance));
}
if (mLightBarController != null) {
mLightBarController.onNavigationBarAppearanceChanged(appearance, nbModeChanged,
- mTransitionMode, navbarColorManagedByIme);
+ mNavigationBarMode, navbarColorManagedByIme);
}
if (mBehavior != behavior) {
mBehavior = behavior;
@@ -1028,16 +1025,16 @@
private void handleTransientChanged() {
mNavigationBarView.onTransientStateChanged(mTransientShown,
mTransientShownFromGestureOnSystemBar);
- final int transitionMode = transitionMode(mTransientShown, mAppearance);
- if (updateTransitionMode(transitionMode) && mLightBarController != null) {
- mLightBarController.onNavigationBarModeChanged(transitionMode);
+ final int barMode = barMode(mTransientShown, mAppearance);
+ if (updateBarMode(barMode) && mLightBarController != null) {
+ mLightBarController.onNavigationBarModeChanged(barMode);
}
}
// Returns true if the bar mode is changed.
- private boolean updateTransitionMode(int barMode) {
- if (mTransitionMode != barMode) {
- mTransitionMode = barMode;
+ private boolean updateBarMode(int barMode) {
+ if (mNavigationBarMode != barMode) {
+ mNavigationBarMode = barMode;
checkNavBarModes();
if (mAutoHideController != null) {
mAutoHideController.touchAutoHide();
@@ -1047,7 +1044,7 @@
return false;
}
- private static @TransitionMode int transitionMode(boolean isTransient, int appearance) {
+ private static @TransitionMode int barMode(boolean isTransient, int appearance) {
final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_NAVIGATION_BARS;
if (isTransient) {
return MODE_SEMI_TRANSPARENT;
@@ -1076,7 +1073,7 @@
| StatusBarManager.DISABLE_SEARCH);
if (masked != mDisabledFlags1) {
mDisabledFlags1 = masked;
- mNavigationBarView.setDisabledFlags(state1, mSysUiFlagsContainer);
+ mNavigationBarView.setDisabledFlags(state1);
updateScreenPinningGestures();
}
@@ -1458,7 +1455,24 @@
mCentralSurfacesOptionalLazy.get().map(CentralSurfaces::isDeviceInteractive)
.orElse(false)
&& mNavigationBarWindowState != WINDOW_STATE_HIDDEN;
- mNavigationBarView.getBarTransitions().transitionTo(mTransitionMode, anim);
+ mNavigationBarView.getBarTransitions().transitionTo(mNavigationBarMode, anim);
+ }
+
+ @Override
+ public void onNavigationModeChanged(int mode) {
+ mNavBarMode = mode;
+
+ if (!QuickStepContract.isGesturalMode(mode)) {
+ // Reset the override alpha
+ if (getBarTransitions() != null) {
+ getBarTransitions().setBackgroundOverrideAlpha(1f);
+ }
+ }
+ updateScreenPinningGestures();
+
+ if (!canShowSecondaryHandle()) {
+ resetSecondaryHandle();
+ }
}
public void disableAnimationsDuringHide(long delay) {
@@ -1599,102 +1613,114 @@
return mNavigationIconHints;
}
- private void setNavigationIconHints(int hints) {
- if (hints == mNavigationIconHints) return;
- if (!isTablet(mContext)) {
- // All IME functions handled by launcher via Sysui flags for large screen
- final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
- final boolean oldBackAlt =
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
- if (newBackAlt != oldBackAlt) {
- mNavigationBarView.onImeVisibilityChanged(newBackAlt);
- mImeVisible = newBackAlt;
- }
-
- mNavigationBarView.setNavigationIconHints(hints);
- }
- if (DEBUG) {
- android.widget.Toast.makeText(mContext,
- "Navigation icon hints = " + hints,
- 500).show();
- }
- mNavigationIconHints = hints;
- }
-
- private final ModeChangedListener mModeChangedListener = new ModeChangedListener() {
- @Override
- public void onNavigationModeChanged(int mode) {
- mNavBarMode = mode;
-
- if (!QuickStepContract.isGesturalMode(mode)) {
- // Reset the override alpha
- if (getBarTransitions() != null) {
- getBarTransitions().setBackgroundOverrideAlpha(1f);
- }
- }
- updateScreenPinningGestures();
-
- if (!canShowSecondaryHandle()) {
- resetSecondaryHandle();
- }
- if (mNavigationBarView != null) {
- mNavigationBarView.setNavBarMode(mode);
- }
- }
- };
-
- private final Gefingerpoken mTouchHandler = new Gefingerpoken() {
- private boolean mDeadZoneConsuming;
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (isGesturalMode(mNavBarMode) && mImeVisible
- && ev.getAction() == MotionEvent.ACTION_DOWN) {
- SysUiStatsLog.write(SysUiStatsLog.IME_TOUCH_REPORTED,
- (int) ev.getX(), (int) ev.getY());
- }
- return shouldDeadZoneConsumeTouchEvents(ev);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- shouldDeadZoneConsumeTouchEvents(ev);
- return false;
- }
-
- private boolean shouldDeadZoneConsumeTouchEvents(MotionEvent event) {
- int action = event.getActionMasked();
- if (action == MotionEvent.ACTION_DOWN) {
- mDeadZoneConsuming = false;
- }
- if (mDeadZone.onTouchEvent(event) || mDeadZoneConsuming) {
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- // Allow gestures starting in the deadzone to be slippery
- mNavigationBarView.setSlippery(true);
- mDeadZoneConsuming = true;
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- // When a gesture started in the deadzone is finished, restore
- // slippery state
- mNavigationBarView.updateSlippery();
- mDeadZoneConsuming = false;
- break;
- }
- return true;
- }
- return false;
- }
- };
-
-
/**
* Injectable factory for construction a {@link NavigationBar}.
*/
- @AssistedFactory
- public interface Factory {
+ public static class Factory {
+ private final Lazy<AssistManager> mAssistManagerLazy;
+ private final AccessibilityManager mAccessibilityManager;
+ private final DeviceProvisionedController mDeviceProvisionedController;
+ private final MetricsLogger mMetricsLogger;
+ private final OverviewProxyService mOverviewProxyService;
+ private final NavigationModeController mNavigationModeController;
+ private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
+ private final StatusBarStateController mStatusBarStateController;
+ private final SysUiState mSysUiFlagsContainer;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+ private final CommandQueue mCommandQueue;
+ private final Optional<Pip> mPipOptional;
+ private final Optional<Recents> mRecentsOptional;
+ private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
+ private final ShadeController mShadeController;
+ private final NotificationRemoteInputManager mNotificationRemoteInputManager;
+ private final NotificationShadeDepthController mNotificationShadeDepthController;
+ private final Handler mMainHandler;
+ private final NavigationBarOverlayController mNavbarOverlayController;
+ private final UiEventLogger mUiEventLogger;
+ private final NavBarHelper mNavBarHelper;
+ private final LightBarController mMainLightBarController;
+ private final LightBarController.Factory mLightBarControllerFactory;
+ private final AutoHideController mMainAutoHideController;
+ private final AutoHideController.Factory mAutoHideControllerFactory;
+ private final Optional<TelecomManager> mTelecomManagerOptional;
+ private final InputMethodManager mInputMethodManager;
+ private final Optional<BackAnimation> mBackAnimation;
+
+ @Inject
+ public Factory(
+ Lazy<AssistManager> assistManagerLazy,
+ AccessibilityManager accessibilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ MetricsLogger metricsLogger,
+ OverviewProxyService overviewProxyService,
+ NavigationModeController navigationModeController,
+ AccessibilityButtonModeObserver accessibilityButtonModeObserver,
+ StatusBarStateController statusBarStateController,
+ SysUiState sysUiFlagsContainer,
+ BroadcastDispatcher broadcastDispatcher,
+ CommandQueue commandQueue,
+ Optional<Pip> pipOptional,
+ Optional<Recents> recentsOptional,
+ Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
+ ShadeController shadeController,
+ NotificationRemoteInputManager notificationRemoteInputManager,
+ NotificationShadeDepthController notificationShadeDepthController,
+ @Main Handler mainHandler,
+ NavigationBarOverlayController navbarOverlayController,
+ UiEventLogger uiEventLogger,
+ NavBarHelper navBarHelper,
+ LightBarController mainLightBarController,
+ LightBarController.Factory lightBarControllerFactory,
+ AutoHideController mainAutoHideController,
+ AutoHideController.Factory autoHideControllerFactory,
+ Optional<TelecomManager> telecomManagerOptional,
+ InputMethodManager inputMethodManager,
+ Optional<BackAnimation> backAnimation) {
+ mAssistManagerLazy = assistManagerLazy;
+ mAccessibilityManager = accessibilityManager;
+ mDeviceProvisionedController = deviceProvisionedController;
+ mMetricsLogger = metricsLogger;
+ mOverviewProxyService = overviewProxyService;
+ mNavigationModeController = navigationModeController;
+ mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
+ mStatusBarStateController = statusBarStateController;
+ mSysUiFlagsContainer = sysUiFlagsContainer;
+ mBroadcastDispatcher = broadcastDispatcher;
+ mCommandQueue = commandQueue;
+ mPipOptional = pipOptional;
+ mRecentsOptional = recentsOptional;
+ mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy;
+ mShadeController = shadeController;
+ mNotificationRemoteInputManager = notificationRemoteInputManager;
+ mNotificationShadeDepthController = notificationShadeDepthController;
+ mMainHandler = mainHandler;
+ mNavbarOverlayController = navbarOverlayController;
+ mUiEventLogger = uiEventLogger;
+ mNavBarHelper = navBarHelper;
+ mMainLightBarController = mainLightBarController;
+ mLightBarControllerFactory = lightBarControllerFactory;
+ mMainAutoHideController = mainAutoHideController;
+ mAutoHideControllerFactory = autoHideControllerFactory;
+ mTelecomManagerOptional = telecomManagerOptional;
+ mInputMethodManager = inputMethodManager;
+ mBackAnimation = backAnimation;
+ }
+
/** Construct a {@link NavigationBar} */
- NavigationBar create(Context context);
+ public NavigationBar create(Context context) {
+ final WindowManager wm = context.getSystemService(WindowManager.class);
+ return new NavigationBar(context, wm, mAssistManagerLazy,
+ mAccessibilityManager, mDeviceProvisionedController, mMetricsLogger,
+ mOverviewProxyService, mNavigationModeController,
+ mAccessibilityButtonModeObserver, mStatusBarStateController,
+ mSysUiFlagsContainer, mBroadcastDispatcher, mCommandQueue, mPipOptional,
+ mRecentsOptional, mCentralSurfacesOptionalLazy,
+ mShadeController, mNotificationRemoteInputManager,
+ mNotificationShadeDepthController, mMainHandler,
+ mNavbarOverlayController, mUiEventLogger, mNavBarHelper,
+ mMainLightBarController, mLightBarControllerFactory,
+ mMainAutoHideController, mAutoHideControllerFactory, mTelecomManagerOptional,
+ mInputMethodManager, mBackAnimation);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index f5abe28..017bbdf 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -65,7 +65,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
-import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.model.SysUiState;
@@ -85,12 +84,13 @@
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoHideController;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;
@@ -101,14 +101,15 @@
import java.util.concurrent.Executor;
import java.util.function.Consumer;
-/** */
-public class NavigationBarView extends FrameLayout {
+public class NavigationBarView extends FrameLayout implements
+ NavigationModeController.ModeChangedListener {
final static boolean DEBUG = false;
final static String TAG = "NavBarView";
final static boolean ALTERNATE_CAR_MODE_UI = false;
private final RegionSamplingHelper mRegionSamplingHelper;
private final int mNavColorSampleMargin;
+ private final SysUiState mSysUiFlagContainer;
// The current view is one of mHorizontal or mVertical depending on the current configuration
View mCurrentView = null;
@@ -196,7 +197,6 @@
* <p>Cache the value here for better performance.</p>
*/
private final boolean mImeCanRenderGesturalNavButtons = canImeRenderGesturalNavButtons();
- private Gefingerpoken mTouchHandler;
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
@@ -333,8 +333,10 @@
mDarkIconColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor);
mIsVertical = false;
mLongClickableAccessibilityButton = false;
+ mNavBarMode = Dependency.get(NavigationModeController.class).addListener(this);
mImeDrawsImeNavBar = Dependency.get(NavigationModeController.class).getImeDrawsImeNavBar();
+ mSysUiFlagContainer = Dependency.get(SysUiState.class);
// Set up the context group of buttons
mContextualButtonGroup = new ContextualButtonGroup(R.id.menu_container);
final ContextualButton imeSwitcherButton = new ContextualButton(R.id.ime_switcher,
@@ -363,6 +365,8 @@
R.drawable.ic_sysbar_rotate_button_cw_start_90,
() -> getDisplay().getRotation());
+ updateRotationButton();
+
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
mConfiguration = new Configuration();
@@ -444,18 +448,19 @@
notifyVerticalChangedListener(mIsVertical);
}
- public void setTouchHandler(Gefingerpoken touchHandler) {
- mTouchHandler = touchHandler;
- }
-
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- return mTouchHandler.onInterceptTouchEvent(event) || super.onInterceptTouchEvent(event);
+ if (isGesturalMode(mNavBarMode) && mImeVisible
+ && event.getAction() == MotionEvent.ACTION_DOWN) {
+ SysUiStatsLog.write(SysUiStatsLog.IME_TOUCH_REPORTED,
+ (int) event.getX(), (int) event.getY());
+ }
+ return shouldDeadZoneConsumeTouchEvents(event) || super.onInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
- mTouchHandler.onTouchEvent(event);
+ shouldDeadZoneConsumeTouchEvents(event);
return super.onTouchEvent(event);
}
@@ -492,6 +497,30 @@
}
}
+ private boolean shouldDeadZoneConsumeTouchEvents(MotionEvent event) {
+ int action = event.getActionMasked();
+ if (action == MotionEvent.ACTION_DOWN) {
+ mDeadZoneConsuming = false;
+ }
+ if (mDeadZone.onTouchEvent(event) || mDeadZoneConsuming) {
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ // Allow gestures starting in the deadzone to be slippery
+ setSlippery(true);
+ mDeadZoneConsuming = true;
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ // When a gesture started in the deadzone is finished, restore slippery state
+ updateSlippery();
+ mDeadZoneConsuming = false;
+ break;
+ }
+ return true;
+ }
+ return false;
+ }
+
public void abortCurrentGesture() {
getHomeButton().abortCurrentGesture();
}
@@ -560,7 +589,7 @@
return (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) == 0;
}
- private boolean isQuickStepSwipeUpEnabled() {
+ public boolean isQuickStepSwipeUpEnabled() {
return mOverviewProxyService.shouldShowSwipeUpUI() && isOverviewEnabled();
}
@@ -589,7 +618,7 @@
/**
* Updates the rotation button based on the current navigation mode.
*/
- void updateRotationButton() {
+ private void updateRotationButton() {
if (isGesturalMode(mNavBarMode)) {
mContextualButtonGroup.removeButton(R.id.rotate_suggestion);
mButtonDispatchers.remove(R.id.rotate_suggestion);
@@ -693,13 +722,25 @@
super.setLayoutDirection(layoutDirection);
}
- void setNavigationIconHints(int hints) {
+ public void setNavigationIconHints(int hints) {
if (hints == mNavigationIconHints) return;
+ final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
+ final boolean oldBackAlt =
+ (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
+ if (newBackAlt != oldBackAlt) {
+ onImeVisibilityChanged(newBackAlt);
+ }
+
+ if (DEBUG) {
+ android.widget.Toast.makeText(getContext(),
+ "Navigation icon hints = " + hints,
+ 500).show();
+ }
mNavigationIconHints = hints;
updateNavButtonIcons();
}
- void onImeVisibilityChanged(boolean visible) {
+ private void onImeVisibilityChanged(boolean visible) {
if (!visible) {
mTransitionListener.onBackAltCleared();
}
@@ -710,7 +751,7 @@
}
}
- void setDisabledFlags(int disabledFlags, SysUiState sysUiState) {
+ public void setDisabledFlags(int disabledFlags) {
if (mDisabledFlags == disabledFlags) return;
final boolean overviewEnabledBefore = isOverviewEnabled();
@@ -723,7 +764,7 @@
updateNavButtonIcons();
updateSlippery();
- updateDisabledSystemUiStateFlags(sysUiState);
+ updateDisabledSystemUiStateFlags();
}
public void updateNavButtonIcons() {
@@ -866,11 +907,10 @@
updateSlippery();
}
- /** */
- public void updateDisabledSystemUiStateFlags(SysUiState sysUiState) {
+ public void updateDisabledSystemUiStateFlags() {
int displayId = mContext.getDisplayId();
- sysUiState.setFlag(SYSUI_STATE_SCREEN_PINNING,
+ mSysUiFlagContainer.setFlag(SYSUI_STATE_SCREEN_PINNING,
ActivityManagerWrapper.getInstance().isScreenPinningActive())
.setFlag(SYSUI_STATE_OVERVIEW_DISABLED,
(mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0)
@@ -912,12 +952,12 @@
* slippery is enabled, touch events will leave the nav bar window and enter into the fullscreen
* app/home window, if not nav bar will receive a cancelled touch event once gesture leaves bar.
*/
- void updateSlippery() {
+ public void updateSlippery() {
setSlippery(!isQuickStepSwipeUpEnabled() ||
(mPanelView != null && mPanelView.isFullyExpanded() && !mPanelView.isCollapsing()));
}
- void setSlippery(boolean slippery) {
+ private void setSlippery(boolean slippery) {
setWindowFlag(WindowManager.LayoutParams.FLAG_SLIPPERY, slippery);
}
@@ -939,7 +979,8 @@
wm.updateViewLayout(navbarView, lp);
}
- void setNavBarMode(int mode) {
+ @Override
+ public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
mImeDrawsImeNavBar = Dependency.get(NavigationModeController.class).getImeDrawsImeNavBar();
mBarTransitions.onNavigationModeChanged(mNavBarMode);
@@ -1282,6 +1323,7 @@
mEdgeBackGestureHandler.onNavBarAttached();
requestApplyInsets();
reorient();
+ onNavigationModeChanged(mNavBarMode);
if (mRotationButtonController != null) {
mRotationButtonController.registerListeners();
}
@@ -1296,6 +1338,7 @@
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
+ Dependency.get(NavigationModeController.class).removeListener(this);
for (int i = 0; i < mButtonDispatchers.size(); ++i) {
mButtonDispatchers.valueAt(i).onDestroy();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 53a27ff..a3dea1c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -101,8 +101,8 @@
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.wm.shell.back.BackAnimation;
@@ -675,7 +675,7 @@
navBarFragment.updateSystemUiStateFlags();
}
if (navBarView != null) {
- navBarView.updateDisabledSystemUiStateFlags(mSysUiState);
+ navBarView.updateDisabledSystemUiStateFlags();
}
if (panelController != null) {
panelController.updateSystemUiStateFlags();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index be1aa10..27cc326 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -758,29 +758,30 @@
mDebugTextUsedYPositions.clear();
}
int y = mTopPadding;
- drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding");
+ drawDebugInfo(canvas, y, Color.RED, /* label= */ "mTopPadding = "+y);
y = getLayoutHeight();
- drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight()");
+ drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight() = "+y);
y = (int) mMaxLayoutHeight;
- drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight");
+ drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight = "+y);
if (mKeyguardBottomPadding >= 0) {
y = getHeight() - (int) mKeyguardBottomPadding;
drawDebugInfo(canvas, y, Color.GRAY,
- /* label= */ "getHeight() - mKeyguardBottomPadding");
+ /* label= */ "getHeight() - mKeyguardBottomPadding = "+y);
}
y = getHeight() - getEmptyBottomMargin();
- drawDebugInfo(canvas, y, Color.GREEN, /* label= */ "getHeight() - getEmptyBottomMargin()");
+ drawDebugInfo(canvas, y, Color.GREEN,
+ /* label= */ "getHeight() - getEmptyBottomMargin() = "+y);
y = (int) (mAmbientState.getStackY());
- drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY()");
+ drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY() = "+y);
y = (int) (mAmbientState.getStackY() + mAmbientState.getStackHeight());
drawDebugInfo(canvas, y, Color.BLUE,
- /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight()");
+ /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight() = "+y);
}
private void drawDebugInfo(Canvas canvas, int y, int color, String label) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 952cd9a..e1f8c35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -202,12 +202,10 @@
float newHeight = state.height;
float newNotificationEnd = newYTranslation + newHeight;
boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && child.isPinned();
- final boolean shadeClosedWithHUN =
- ambientState.isShadeOpening() && !ambientState.isShadeExpanded();
if (mClipNotificationScrollToTop
&& (!state.inShelf || (isHeadsUp && !firstHeadsUp))
&& newYTranslation < clipStart
- && shadeClosedWithHUN) {
+ && !ambientState.isShadeExpanded()) {
// The previous view is overlapping on top, clip!
float overlapAmount = clipStart - newYTranslation;
state.clipTopAmount = (int) overlapAmount;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index a0aa267..eb1e1a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -91,10 +91,10 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.phone.AutoHideController;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.utils.leaks.LeakCheckedTest;
@@ -387,14 +387,14 @@
DeviceProvisionedController deviceProvisionedController =
mock(DeviceProvisionedController.class);
when(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
- return spy(new NavigationBar(context,
- mWindowManager,
+ NavigationBar.Factory factory = new NavigationBar.Factory(
() -> mAssistManager,
mock(AccessibilityManager.class),
deviceProvisionedController,
new MetricsLogger(),
mOverviewProxyService,
mNavigationModeController,
+ mock(AccessibilityButtonModeObserver.class),
mStatusBarStateController,
mMockSysUiState,
mBroadcastDispatcher,
@@ -415,7 +415,8 @@
mAutoHideControllerFactory,
Optional.of(mTelecomManager),
mInputMethodManager,
- Optional.of(mock(BackAnimation.class))));
+ Optional.of(mock(BackAnimation.class)));
+ return spy(factory.create(context));
}
private void processAllMessages() {
diff --git a/proto/src/camera.proto b/proto/src/camera.proto
index 4082118..38d74e4 100644
--- a/proto/src/camera.proto
+++ b/proto/src/camera.proto
@@ -66,5 +66,5 @@
// The dynamic range profile of the stream
optional int64 dynamic_range_profile = 14;
// The stream use case
- optional int32 stream_use_case = 15;
+ optional int64 stream_use_case = 15;
}
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index e10151d..1af35af 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -89,8 +89,6 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
-import android.os.storage.IStorageManager;
-import android.os.storage.StorageManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -325,7 +323,6 @@
private final ActivityManagerInternal mActivityManagerInternal;
private PowerManager mPowerManager;
private final AlarmManager mAlarmManager;
- private final IStorageManager mStorageManager;
private final BackupManagerConstants mConstants;
private final BackupWakeLock mWakelock;
private final BackupHandler mBackupHandler;
@@ -536,7 +533,6 @@
mBackupPasswordManager = null;
mPackageManagerBinder = null;
mActivityManager = null;
- mStorageManager = null;
mBackupManagerBinder = null;
mScheduledBackupEligibility = null;
}
@@ -560,7 +556,6 @@
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
Objects.requireNonNull(parent, "parent cannot be null");
mBackupManagerBinder = BackupManagerService.asInterface(parent.asBinder());
@@ -2077,26 +2072,6 @@
}
}
- /** For adb backup/restore. */
- public boolean deviceIsEncrypted() {
- try {
- return mStorageManager.getEncryptionState()
- != StorageManager.ENCRYPTION_STATE_NONE
- && mStorageManager.getPasswordType()
- != StorageManager.CRYPT_TYPE_DEFAULT;
- } catch (Exception e) {
- // If we can't talk to the storagemanager service we have a serious problem; fail
- // "secure" i.e. assuming that the device is encrypted.
- Slog.e(
- TAG,
- addUserIdToLogMessage(
- mUserId,
- "Unable to communicate with storagemanager service: "
- + e.getMessage()));
- return true;
- }
- }
-
// ----- Full-data backup scheduling -----
/**
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index 7ee307e..ec58e17 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -320,12 +320,6 @@
try {
boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0);
- // Only allow encrypted backups of encrypted devices
- if (mUserBackupManagerService.deviceIsEncrypted() && !encrypting) {
- Slog.e(TAG, "Unencrypted backup of encrypted device; aborting");
- return;
- }
-
OutputStream finalOutput = ofstream;
// Verify that the given password matches the currently-active
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index be2b7f7..f1fa982 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -131,7 +131,7 @@
final UserManager userManager = context.getSystemService(UserManager.class);
final int result = userManager.removeUserWhenPossible(
UserHandle.of(userId), /* overrideDevicePolicy= */ false);
- if (result == UserManager.REMOVE_RESULT_ERROR) {
+ if (!UserManager.isRemoveResultSuccessful(result)) {
Slogf.e(TAG, "Can't remove user %d", userId);
return false;
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7075ed3..677fc79 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3129,203 +3129,6 @@
}
}
- @Override
- public int getEncryptionState() {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- try {
- return mVold.fdeComplete();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
- }
- }
-
- @Override
- public int decryptStorage(String password) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (TextUtils.isEmpty(password)) {
- throw new IllegalArgumentException("password cannot be empty");
- }
-
- if (DEBUG_EVENTS) {
- Slog.i(TAG, "decrypting storage...");
- }
-
- try {
- mVold.fdeCheckPassword(password);
- mHandler.postDelayed(() -> {
- try {
- mVold.fdeRestart();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- }
- }, DateUtils.SECOND_IN_MILLIS);
- return 0;
- } catch (ServiceSpecificException e) {
- Slog.e(TAG, "fdeCheckPassword failed", e);
- return e.errorCode;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
- }
- }
-
- @Override
- public int encryptStorage(int type, String password) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
- password = "";
- } else if (TextUtils.isEmpty(password)) {
- throw new IllegalArgumentException("password cannot be empty");
- }
-
- if (DEBUG_EVENTS) {
- Slog.i(TAG, "encrypting storage...");
- }
-
- try {
- mVold.fdeEnable(type, password, 0);
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
-
- return 0;
- }
-
- /** Set the password for encrypting the main key.
- * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
- * @param password The password to set.
- */
- @Override
- public int changeEncryptionPassword(int type, String password) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (StorageManager.isFileEncryptedNativeOnly()) {
- // Not supported on FBE devices
- return -1;
- }
-
- if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
- password = "";
- } else if (TextUtils.isEmpty(password)) {
- throw new IllegalArgumentException("password cannot be empty");
- }
-
- if (DEBUG_EVENTS) {
- Slog.i(TAG, "changing encryption password...");
- }
-
- try {
- mVold.fdeChangePassword(type, password);
- return 0;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
- }
-
- /**
- * Validate a user-supplied password string with cryptfs
- */
- @Override
- public int verifyEncryptionPassword(String password) throws RemoteException {
- // Only the system process is permitted to validate passwords
- if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
- throw new SecurityException("no permission to access the crypt keeper");
- }
-
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (TextUtils.isEmpty(password)) {
- throw new IllegalArgumentException("password cannot be empty");
- }
-
- if (DEBUG_EVENTS) {
- Slog.i(TAG, "validating encryption password...");
- }
-
- try {
- mVold.fdeVerifyPassword(password);
- return 0;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
- }
-
- /**
- * Get the type of encryption used to encrypt the main key.
- * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
- */
- @Override
- public int getPasswordType() {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- try {
- return mVold.fdeGetPasswordType();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return -1;
- }
- }
-
- /**
- * Set a field in the crypto header.
- * @param field field to set
- * @param contents contents to set in field
- */
- @Override
- public void setField(String field, String contents) throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (!StorageManager.isBlockEncrypted()) {
- // Only supported on FDE devices
- return;
- }
-
- try {
- mVold.fdeSetField(field, contents);
- return;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return;
- }
- }
-
- /**
- * Gets a field from the crypto header.
- * @param field field to get
- * @return contents of field
- */
- @Override
- public String getField(String field) throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "no permission to access the crypt keeper");
-
- if (!StorageManager.isBlockEncrypted()) {
- // Only supported on FDE devices
- return null;
- }
-
- try {
- return mVold.fdeGetField(field);
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return null;
- }
- }
-
/**
* Is userdata convertible to file based encryption?
* @return non zero for convertible
@@ -3408,33 +3211,6 @@
}
@Override
- public String getPassword() throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "only keyguard can retrieve password");
-
- try {
- return mVold.fdeGetPassword();
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return null;
- }
- }
-
- @Override
- public void clearPassword() throws RemoteException {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
- "only keyguard can clear password");
-
- try {
- mVold.fdeClearPassword();
- return;
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- return;
- }
- }
-
- @Override
public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 7765ab3..9ae6750 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -136,8 +136,8 @@
try {
if (mSensorPrivacyManager != null
&& mSensorPrivacyManager
- .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA,
- getTargetUserId())) {
+ .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+ SensorPrivacyManager.Sensors.CAMERA)) {
onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
index efedcf8..ded1810 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
@@ -96,7 +96,8 @@
protected void startHalOperation() {
if (mSensorPrivacyManager != null
&& mSensorPrivacyManager
- .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, getTargetUserId())) {
+ .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+ SensorPrivacyManager.Sensors.CAMERA)) {
onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
return;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 8d76e9f..1935a5b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -109,7 +109,8 @@
if (mSensorPrivacyManager != null
&& mSensorPrivacyManager
- .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, getTargetUserId())) {
+ .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
+ SensorPrivacyManager.Sensors.CAMERA)) {
onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
return;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 52834cb..436cc69 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -252,8 +252,6 @@
private final RebootEscrowManager mRebootEscrowManager;
- private boolean mFirstCallToVold;
-
// Current password metric for all users on the device. Updated when user unlocks
// the device or changes password. Removed when user is stopped.
@GuardedBy("this")
@@ -597,8 +595,6 @@
mStrongAuth = injector.getStrongAuth();
mActivityManager = injector.getActivityManager();
- mFirstCallToVold = true;
-
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_STARTING);
@@ -2474,77 +2470,6 @@
});
}
- private LockscreenCredential createPattern(String patternString) {
- final byte[] patternBytes = patternString.getBytes();
- LockscreenCredential pattern = LockscreenCredential.createPattern(
- LockPatternUtils.byteArrayToPattern(patternBytes));
- Arrays.fill(patternBytes, (byte) 0);
- return pattern;
- }
-
- @Override
- public boolean checkVoldPassword(int userId) {
- if (!mFirstCallToVold) {
- return false;
- }
- mFirstCallToVold = false;
-
- checkPasswordReadPermission();
-
- // There's no guarantee that this will safely connect, but if it fails
- // we will simply show the lock screen when we shouldn't, so relatively
- // benign. There is an outside chance something nasty would happen if
- // this service restarted before vold stales out the password in this
- // case. The nastiness is limited to not showing the lock screen when
- // we should, within the first minute of decrypting the phone if this
- // service can't connect to vold, it restarts, and then the new instance
- // does successfully connect.
- final IStorageManager service = mInjector.getStorageManager();
- // TODO(b/120484642): Update vold to return a password as a byte array
- String password;
- final long identity = Binder.clearCallingIdentity();
- try {
- password = service.getPassword();
- service.clearPassword();
- } catch (RemoteException e) {
- Slog.w(TAG, "vold getPassword() failed", e);
- return false;
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- if (TextUtils.isEmpty(password)) {
- return false;
- }
-
- try {
- final LockscreenCredential credential;
- switch (getCredentialTypeInternal(userId)) {
- case CREDENTIAL_TYPE_PATTERN:
- credential = createPattern(password);
- break;
- case CREDENTIAL_TYPE_PIN:
- credential = LockscreenCredential.createPin(password);
- break;
- case CREDENTIAL_TYPE_PASSWORD:
- credential = LockscreenCredential.createPassword(password);
- break;
- default:
- credential = null;
- Slog.e(TAG, "Unknown credential type");
- }
-
- if (credential != null
- && checkCredential(credential, userId, null /* progressCallback */)
- .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
- return true;
- }
- } catch (Exception e) {
- Slog.e(TAG, "checkVoldPassword failed: ", e);
- }
-
- return false;
- }
-
private void removeUser(int userId, boolean unknownUser) {
Slog.i(TAG, "RemoveUser: " + userId);
removeBiometricsForUser(userId);
diff --git a/services/core/java/com/android/server/pm/AppIdSettingMap.java b/services/core/java/com/android/server/pm/AppIdSettingMap.java
index bbef237..b41a0b8 100644
--- a/services/core/java/com/android/server/pm/AppIdSettingMap.java
+++ b/services/core/java/com/android/server/pm/AppIdSettingMap.java
@@ -17,46 +17,131 @@
package com.android.server.pm;
import android.os.Process;
+import android.util.Log;
+import com.android.server.utils.WatchedArrayList;
import com.android.server.utils.WatchedSparseArray;
+import com.android.server.utils.Watcher;
/**
- * A wrapper over {@link WatchedSparseArray} that tracks the current maximum App ID.
+ * A wrapper over {@link WatchedArrayList} that tracks the current (app ID -> SettingBase) mapping
+ * for non-system apps. Also tracks system app settings in an {@link WatchedSparseArray}.
*/
-public class AppIdSettingMap extends WatchedSparseArray<SettingBase> {
- private int mCurrentMaxAppId;
+final class AppIdSettingMap {
+ /**
+ * We use an ArrayList instead of an SparseArray for non system apps because the number of apps
+ * might be big, and only ArrayList gives us a constant lookup time. For a given app ID, the
+ * index to the corresponding SettingBase object is (appId - FIRST_APPLICATION_ID). If an app ID
+ * doesn't exist (i.e., app is not installed), we fill the corresponding entry with null.
+ */
+ private WatchedArrayList<SettingBase> mNonSystemSettings = new WatchedArrayList<>();
+ private WatchedSparseArray<SettingBase> mSystemSettings = new WatchedSparseArray<>();
+ private int mFirstAvailableAppId = Process.FIRST_APPLICATION_UID;
- @Override
- public void put(int key, SettingBase value) {
- if (key > mCurrentMaxAppId) {
- mCurrentMaxAppId = key;
+ /** Returns true if the requested AppID was valid and not already registered. */
+ public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {
+ if (appId >= Process.FIRST_APPLICATION_UID) {
+ int size = mNonSystemSettings.size();
+ final int index = appId - Process.FIRST_APPLICATION_UID;
+ // fill the array until our index becomes valid
+ while (index >= size) {
+ mNonSystemSettings.add(null);
+ size++;
+ }
+ if (mNonSystemSettings.get(index) != null) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Adding duplicate app id: " + appId
+ + " name=" + name);
+ return false;
+ }
+ mNonSystemSettings.set(index, setting);
+ } else {
+ if (mSystemSettings.get(appId) != null) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Adding duplicate shared id: " + appId
+ + " name=" + name);
+ return false;
+ }
+ mSystemSettings.put(appId, setting);
}
- super.put(key, value);
+ return true;
}
- @Override
+ public SettingBase getSetting(int appId) {
+ if (appId >= Process.FIRST_APPLICATION_UID) {
+ final int size = mNonSystemSettings.size();
+ final int index = appId - Process.FIRST_APPLICATION_UID;
+ return index < size ? mNonSystemSettings.get(index) : null;
+ } else {
+ return mSystemSettings.get(appId);
+ }
+ }
+
+ public void removeSetting(int appId) {
+ if (appId >= Process.FIRST_APPLICATION_UID) {
+ final int size = mNonSystemSettings.size();
+ final int index = appId - Process.FIRST_APPLICATION_UID;
+ if (index < size) {
+ mNonSystemSettings.set(index, null);
+ }
+ } else {
+ mSystemSettings.remove(appId);
+ }
+ setFirstAvailableAppId(appId + 1);
+ }
+
+ // This should be called (at least) whenever an application is removed
+ private void setFirstAvailableAppId(int uid) {
+ if (uid > mFirstAvailableAppId) {
+ mFirstAvailableAppId = uid;
+ }
+ }
+
+ public void replaceSetting(int appId, SettingBase setting) {
+ if (appId >= Process.FIRST_APPLICATION_UID) {
+ final int size = mNonSystemSettings.size();
+ final int index = appId - Process.FIRST_APPLICATION_UID;
+ if (index < size) {
+ mNonSystemSettings.set(index, setting);
+ } else {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: calling replaceAppIdLpw to"
+ + " replace SettingBase at appId=" + appId
+ + " but nothing is replaced.");
+ }
+ } else {
+ mSystemSettings.put(appId, setting);
+ }
+ }
+
+ /** Returns a new AppID or -1 if we could not find an available AppID to assign */
+ public int acquireAndRegisterNewAppId(SettingBase obj) {
+ final int size = mNonSystemSettings.size();
+ for (int i = mFirstAvailableAppId - Process.FIRST_APPLICATION_UID; i < size; i++) {
+ if (mNonSystemSettings.get(i) == null) {
+ mNonSystemSettings.set(i, obj);
+ return Process.FIRST_APPLICATION_UID + i;
+ }
+ }
+
+ // None left?
+ if (size > (Process.LAST_APPLICATION_UID - Process.FIRST_APPLICATION_UID)) {
+ return -1;
+ }
+
+ mNonSystemSettings.add(obj);
+ return Process.FIRST_APPLICATION_UID + size;
+ }
+
public AppIdSettingMap snapshot() {
AppIdSettingMap l = new AppIdSettingMap();
- snapshot(l, this);
+ mNonSystemSettings.snapshot(l.mNonSystemSettings, mNonSystemSettings);
+ mSystemSettings.snapshot(l.mSystemSettings, mSystemSettings);
return l;
}
- /**
- * @return the maximum of all the App IDs that have been added to the map. 0 if map is empty.
- */
- public int getCurrentMaxAppId() {
- return mCurrentMaxAppId;
- }
-
- /**
- * @return the next available App ID that has not been added to the map
- */
- public int getNextAvailableAppId() {
- if (mCurrentMaxAppId == 0) {
- // No app id has been added yet
- return Process.FIRST_APPLICATION_UID;
- } else {
- return mCurrentMaxAppId + 1;
- }
+ public void registerObserver(Watcher observer) {
+ mNonSystemSettings.registerObserver(observer);
+ mSystemSettings.registerObserver(observer);
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6ccaae1..698dbe9 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -62,7 +62,6 @@
import android.os.Message;
import android.os.PatternMatcher;
import android.os.PersistableBundle;
-import android.os.Process;
import android.os.SELinux;
import android.os.SystemClock;
import android.os.Trace;
@@ -408,8 +407,6 @@
int[] excludedUserIds;
}
- private static int mFirstAvailableUid = Process.FIRST_APPLICATION_UID;
-
/** Map from volume UUID to {@link VersionInfo} */
@Watched
private final WatchedArrayMap<String, VersionInfo> mVersion = new WatchedArrayMap<>();
@@ -472,10 +469,8 @@
@Watched
final WatchedArrayMap<String, SharedUserSetting> mSharedUsers = new WatchedArrayMap<>();
- @Watched
+ @Watched(manual = true)
private final AppIdSettingMap mAppIds;
- @Watched
- private final AppIdSettingMap mOtherAppIds;
// For reading/writing settings file.
@Watched
@@ -565,7 +560,6 @@
mCrossProfileIntentResolvers.registerObserver(mObserver);
mSharedUsers.registerObserver(mObserver);
mAppIds.registerObserver(mObserver);
- mOtherAppIds.registerObserver(mObserver);
mRenamedPackages.registerObserver(mObserver);
mNextAppLinkGeneration.registerObserver(mObserver);
mDefaultBrowserApp.registerObserver(mObserver);
@@ -592,7 +586,6 @@
mLock = new PackageManagerTracedLock();
mPackages.putAll(pkgSettings);
mAppIds = new AppIdSettingMap();
- mOtherAppIds = new AppIdSettingMap();
mSystemDir = null;
mPermissions = null;
mRuntimePermissionsPersistence = null;
@@ -629,7 +622,6 @@
mLock = lock;
mAppIds = new AppIdSettingMap();
- mOtherAppIds = new AppIdSettingMap();
mPermissions = new LegacyPermissionSettings(lock);
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
runtimePermissionsPersistence, new Consumer<Integer>() {
@@ -710,7 +702,6 @@
mCrossProfileIntentResolvers, r.mCrossProfileIntentResolvers);
mSharedUsers.snapshot(r.mSharedUsers);
mAppIds = r.mAppIds.snapshot();
- mOtherAppIds = r.mOtherAppIds.snapshot();
WatchedArrayList.snapshot(
mPastSignatures, r.mPastSignatures);
WatchedArrayMap.snapshot(
@@ -782,7 +773,7 @@
SharedUserSetting s = mSharedUsers.get(name);
if (s == null && create) {
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
- s.mAppId = acquireAndRegisterNewAppIdLPw(s);
+ s.mAppId = mAppIds.acquireAndRegisterNewAppId(s);
if (s.mAppId < 0) {
// < 0 means we couldn't assign a userid; throw exception
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
@@ -890,7 +881,7 @@
pkgPrivateFlags, 0 /*userId*/, usesSdkLibraries, usesSdkLibrariesVersions,
usesStaticLibraries, usesStaticLibrariesVersions, mimeGroups, domainSetId);
p.setAppId(uid);
- if (registerExistingAppIdLPw(uid, p, name)) {
+ if (mAppIds.registerExistingAppId(uid, p, name)) {
mPackages.put(name, p);
return p;
}
@@ -909,7 +900,7 @@
}
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
s.mAppId = uid;
- if (registerExistingAppIdLPw(uid, s, name)) {
+ if (mAppIds.registerExistingAppId(uid, s, name)) {
mSharedUsers.put(name, s);
return s;
}
@@ -1210,11 +1201,11 @@
final boolean createdNew;
if (p.getAppId() == 0 || forceNew) {
// Assign new user ID
- p.setAppId(acquireAndRegisterNewAppIdLPw(p));
+ p.setAppId(mAppIds.acquireAndRegisterNewAppId(p));
createdNew = true;
} else {
// Add new setting to list of user IDs
- createdNew = registerExistingAppIdLPw(p.getAppId(), p, p.getPackageName());
+ createdNew = mAppIds.registerExistingAppId(p.getAppId(), p, p.getPackageName());
}
if (p.getAppId() < 0) {
PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -1304,11 +1295,11 @@
Object userIdPs = getSettingLPr(p.getAppId());
if (sharedUser == null) {
if (userIdPs != null && userIdPs != p) {
- replaceAppIdLPw(p.getAppId(), p);
+ mAppIds.replaceSetting(p.getAppId(), p);
}
} else {
if (userIdPs != null && userIdPs != sharedUser) {
- replaceAppIdLPw(p.getAppId(), sharedUser);
+ mAppIds.replaceSetting(p.getAppId(), sharedUser);
}
}
}
@@ -1357,73 +1348,22 @@
mInstallerPackages.remove(packageName);
}
- /** Returns true if the requested AppID was valid and not already registered. */
- private boolean registerExistingAppIdLPw(int appId, SettingBase obj, Object name) {
- if (appId > Process.LAST_APPLICATION_UID) {
- return false;
- }
-
- if (appId >= Process.FIRST_APPLICATION_UID) {
- if (mAppIds.get(appId) != null) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Adding duplicate app id: " + appId
- + " name=" + name);
- return false;
- }
- mAppIds.put(appId, obj);
- } else {
- if (mOtherAppIds.get(appId) != null) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Adding duplicate shared id: " + appId
- + " name=" + name);
- return false;
- }
- mOtherAppIds.put(appId, obj);
- }
- return true;
- }
-
/** Gets the setting associated with the provided App ID */
public SettingBase getSettingLPr(int appId) {
- if (appId >= Process.FIRST_APPLICATION_UID) {
- return mAppIds.get(appId);
- } else {
- return mOtherAppIds.get(appId);
- }
+ return mAppIds.getSetting(appId);
}
/** Unregisters the provided app ID. */
void removeAppIdLPw(int appId) {
- if (appId >= Process.FIRST_APPLICATION_UID) {
- mAppIds.remove(appId);
- } else {
- mOtherAppIds.remove(appId);
- }
- setFirstAvailableUid(appId + 1);
+ mAppIds.removeSetting(appId);
}
-
- private void replaceAppIdLPw(int appId, SettingBase obj) {
- if (appId >= Process.FIRST_APPLICATION_UID) {
- if (appId <= mAppIds.getCurrentMaxAppId()) {
- mAppIds.put(appId, obj);
- } else {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Error in package manager settings: calling replaceAppIdLpw to"
- + " replace SettingBase at appId=" + appId
- + " but nothing is replaced.");
- }
- } else {
- mOtherAppIds.put(appId, obj);
- }
- }
-
/**
* Transparently convert a SharedUserSetting into PackageSettings without changing appId.
* The sharedUser passed to this method has to be {@link SharedUserSetting#isSingleUser()}.
*/
void convertSharedUserSettingsLPw(SharedUserSetting sharedUser) {
final PackageSetting ps = sharedUser.getPackageSettings().valueAt(0);
- replaceAppIdLPw(sharedUser.getAppId(), ps);
+ mAppIds.replaceSetting(sharedUser.getAppId(), ps);
// Unlink the SharedUserSetting
ps.setSharedUserAppId(INVALID_UID);
@@ -4287,32 +4227,6 @@
}
}
- // This should be called (at least) whenever an application is removed
- private void setFirstAvailableUid(int uid) {
- if (uid > mFirstAvailableUid) {
- mFirstAvailableUid = uid;
- }
- }
-
- /** Returns a new AppID or -1 if we could not find an available AppID to assign */
- private int acquireAndRegisterNewAppIdLPw(SettingBase obj) {
- final int nextAvailableAppId = mAppIds.getNextAvailableAppId();
- for (int uid = mFirstAvailableUid; uid < nextAvailableAppId; uid++) {
- if (mAppIds.get(uid) == null) {
- mAppIds.put(uid, obj);
- return uid;
- }
- }
-
- // None left?
- if (nextAvailableAppId > Process.LAST_APPLICATION_UID) {
- return -1;
- }
-
- mAppIds.put(nextAvailableAppId, obj);
- return nextAvailableAppId;
- }
-
public VerifierDeviceIdentity getVerifierDeviceIdentityLPw(@NonNull Computer computer) {
if (mVerifierDeviceIdentity == null) {
mVerifierDeviceIdentity = VerifierDeviceIdentity.generate();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 1cf2dc5..25fe000 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -488,7 +488,8 @@
mShortcutBitmapSaver = new ShortcutBitmapSaver(this);
mShortcutDumpFiles = new ShortcutDumpFiles(this);
mIsAppSearchEnabled = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, true);
+ SystemUiDeviceConfigFlags.SHORTCUT_APPSEARCH_INTEGRATION, true)
+ && !injectIsLowRamDevice();
if (onlyForPackageManagerApis) {
return; // Don't do anything further. For unit tests only.
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index eae7658..34b7ad4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4638,12 +4638,12 @@
final String restriction = getUserRemovalRestriction(userId);
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
- return UserManager.REMOVE_RESULT_ERROR;
+ return UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION;
}
}
if (userId == UserHandle.USER_SYSTEM) {
Slog.e(LOG_TAG, "System user cannot be removed.");
- return UserManager.REMOVE_RESULT_ERROR;
+ return UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER;
}
final long ident = Binder.clearCallingIdentity();
@@ -4655,7 +4655,7 @@
if (userData == null) {
Slog.e(LOG_TAG,
"Cannot remove user " + userId + ", invalid user id provided.");
- return UserManager.REMOVE_RESULT_ERROR;
+ return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND;
}
if (mRemovingUserIds.get(userId)) {
diff --git a/services/core/java/com/android/server/wm/BLASTSync.md b/services/core/java/com/android/server/wm/BLASTSync.md
new file mode 100644
index 0000000..2f39d6d
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BLASTSync.md
@@ -0,0 +1,108 @@
+= What does it mean for BLAST Sync to work? =
+There are two BLAST sync primitives on the server side, BLASTSyncEngine and applyWithNextDraw.
+Both of them are used to solve subclasses of this category of problem:
+ 1. You have some server side changes, which will trigger both WM/SysUI initiated SurfaceControl.Transactions,
+ and also trigger a client redraw/update
+ 2. You want to synchronize the redraw of those clients with the application of those WM/SysUI side changes.
+
+Put simply, you would like to synchronize the graphical effects of some WM changes with the graphical output of various windows
+observing those changes.
+
+To talk about exactly what the primitives guarantee, we need to clarify what we mean by server side changes.
+In this document we will use a term syncable state to refer to any state mutated under the WindowManager lock
+which when observed by the client, produces a visible outcome in the produced frame.
+For example the current Configuration.
+
+The guarantee provided by Server-side BLAST Sync Primitives is thus:
+Guarantee 1: If you make a set of changes to syncable state, at the same time that you begin a sync,
+then the first frame drawn by the client after observing the syncable state will be sent in a transaction
+to the consumer of the sync which was begun, rather than directly sent to SurfaceFlinger.
+
+Here "at the same time" means in the same critical section (while holding the WM lock)
+For example this guarantee means that you can write code like:
+ window.performConfigurationChange(someConfiguration)
+ window.applyOnNextDraw(consumer)
+And the consumer will always be passed the first frame containing the configuration change. This can work with any
+syncable state not just Configuration.
+
+The following is the protocol and additional requirements for BLAST sync, and an analysis of why it is correct. Due to time
+constraints we analyze it for a single window only (as this is actually the hard part).
+
+Protocol requirements:
+ Server protocol, precondition, begin a syncSeqId integer per window at 0:
+ SA: Enter the critical section
+ SB: Change syncable state, any number of times, prepare any number of syncs (and
+ increment the seqId if a sync was prepared, assosciate it with the sync)
+ SC: Leave the critical section
+ SD: Send syncable state updates to the client, always paired with the current seqId
+ SE: When the client calls finishDrawing, execute the consumer for each sync with
+ seqId <= the seqId which the client passed to finishDrawing
+ Client protocol:
+ CA: Observe state and seqid changes up until a fixed frame deadline, then execute performTraversals
+ CB: If the seqId is incremeneted at the time of the frame deadline, configure the renderer to
+ redirect the next draw in to a transaction, record the seqId at the time
+ CC: When the draw is finished, send the transaction containing the draw to WM with the
+ previously recorded seqId
+ Additional requirements/assumptions:
+ 1. The server may only send changes to the syncable state paired with the seqId. The client may
+ only receive them together (e.g. not from other sources)
+ 2. In between changing and sending syncable state, the lock must be released and acquired again
+ 3. The client wont draw a frame reflecting syncable state changes without passing through "performTraversals"
+ 4. Drawing never fails
+ 5. There are no blocking calls between the client or the server
+
+Note that the server can begin the protocol at any time, so it may be possible for the client to proceed through
+phases SA, SB, SC, and SD multiple times before the client receives any messages.
+
+To show that the guarantee can't be violated, we use a notation of sequences, where we describe interleaving
+of protocol events. For duplicate events, we attach a number, e.g. SA_1, SA_2.
+
+We proceed by contradiction, imagine there was some sequence (..., SA_N, ...) for which the guarantee was
+not upheld. This means that either
+ 1. finishDrawing with the assosciate seqId was never sent to the server OR
+ 2. It was sent too late (after the first frame was sent to SF instead of WM) OR
+ 3. It was sent too early (not containing the state changes originating with SA_N)
+If it was sent neither too late, nor too early, and contained the assosciated seqId, then protocol step SE
+says that the frame will be passed to the consumer and we uphold our guarantee.
+
+The first case is impossible because step SD says that the server always sends the seqId if a sync was prepared.
+If we send it the client must receive it. Since we only increment the seqId, and the client only takes the
+seqId from us (requirement 1, protocol step SB), the received ID must be higher than the clients previous seqId.
+CA says that performTraversals will execute, and CB says that when it does, if the seqId is higher than before
+it will schedule the render to sync. Requirement 4 says drawing never fails, so CC must execute, and so we will always
+eventually send every seqId (or a seqId > than it) back to the server.
+
+It also can't be sent too late. By requirement 2 we must release and acquire the lock
+after after changing and before emitting syncable state changes. This means it's guaranteed
+that even in an ordering like AcquireLock, ChangeState, PrepareSync, Release lock we can't
+send the state changes before prepareSync, and so they can always include at least the seqId
+assosciated with changestate (or a later one).
+Since we only receive the SeqId with the State changes (requirement 1),
+and we wont draw state changes without passing through perform traversals (requirement 3) the first frame
+containing the state change must have been generated by a call to performTraversals which also observed
+the seqId change, and so it will appropriately configure the renderer.
+
+By the same argument it can't be sent too early! Since we only send seqIds we receive from the server,
+and we only send seqIds after completing a drawing pass of the assosciated state.
+
+So we can see that no matter at what time the server makes syncable state changes, the first frame will
+always be delivered to the draw handler. Assuming that the client and server uphold this protocol and these
+requirements.
+
+The trickiest part of the implementation at the moment is due to assosciating seqId. Currently we send one of the most
+most important pieces of syncable state (configuration) over multiple channels. Namely ClientTransaction
+and MSG_RESIZED. The ordering of these relative to sync preparation in server code is undefined, in fact we have cases like
+this all the time:
+ acquireLock()
+ changeConfiguration()
+ // time passes, but still in critical section
+ prepareSync()
+ releaseLock()
+This is exactly the kind of case Guarantee 1 mentions as an example. In previous incarnations of the code this worked
+because relayoutWindow needed to acquire the same lock and relayoutWindow was a necessary part of completing sync.
+
+Now that we have no barrier, that could create issues, because at the time we change configuration (and send the change
+to the client via ClientTransaction), we haven't even incremented the seqId yet, and so how can the client observe it
+at the same time as the state? We solve this by pushing all client communication through a handler thread that has to
+acquire the lock. This ensures we uphold requirement 2.
+
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 23f14a7..dbc0141 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -25,6 +25,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
+import android.os.Bundle;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -44,7 +45,11 @@
class BackNavigationController {
private static final String TAG = "BackNavigationController";
- private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
+ // By default, enable new back dispatching without any animations.
+ private static final int BACK_PREDICTABILITY_PROP =
+ SystemProperties.getInt("persist.debug.back_predictability", 1);
+ private static final int ANIMATIONS_MASK = 1 << 1;
+ private static final int SCREENSHOT_MASK = 1 << 2;
@Nullable
private TaskSnapshotController mTaskSnapshotController;
@@ -53,11 +58,15 @@
* Returns true if the back predictability feature is enabled
*/
static boolean isEnabled() {
- return SystemProperties.getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
+ return BACK_PREDICTABILITY_PROP > 0;
}
static boolean isScreenshotEnabled() {
- return false;
+ return (BACK_PREDICTABILITY_PROP & SCREENSHOT_MASK) != 0;
+ }
+
+ private static boolean isAnimationEnabled() {
+ return (BACK_PREDICTABILITY_PROP & ANIMATIONS_MASK) != 0;
}
/**
@@ -93,14 +102,17 @@
ActivityRecord prev;
WindowContainer<?> removedWindowContainer;
ActivityRecord activityRecord;
+ ActivityRecord prevTaskTopActivity = null;
SurfaceControl animationLeashParent;
WindowConfiguration taskWindowConfiguration;
HardwareBuffer screenshotBuffer = null;
+ SurfaceControl screenshotSurface;
int prevTaskId;
int prevUserId;
RemoteAnimationTarget topAppTarget;
SurfaceControl animLeash;
- IOnBackInvokedCallback callback = null;
+ IOnBackInvokedCallback applicationCallback = null;
+ IOnBackInvokedCallback systemCallback = null;
synchronized (task.mWmService.mGlobalLock) {
@@ -116,15 +128,14 @@
removedWindowContainer = activityRecord;
taskWindowConfiguration = window.getWindowConfiguration();
}
- IOnBackInvokedCallback applicationCallback = null;
- IOnBackInvokedCallback systemCallback = null;
if (window != null) {
applicationCallback = window.getApplicationOnBackInvokedCallback();
- callback = applicationCallback;
- if (callback == null) {
- systemCallback = window.getSystemOnBackInvokedCallback();
- callback = systemCallback;
- }
+ systemCallback = window.getSystemOnBackInvokedCallback();
+ }
+ if (applicationCallback == null && systemCallback == null) {
+ // Return null when either there's no window, or apps have just initialized and
+ // have not finished registering callbacks.
+ return null;
}
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, "
@@ -133,24 +144,24 @@
task, activityRecord, applicationCallback, systemCallback);
// TODO Temp workaround for Sysui until b/221071505 is fixed
- if (activityRecord == null && callback != null) {
+ if (activityRecord == null && applicationCallback != null) {
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
null /* topWindowLeash */, null /* screenshotSurface */,
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
null /* onBackNavigationDone */,
- callback /* onBackInvokedCallback */);
+ applicationCallback /* onBackInvokedCallback */);
}
// For IME and Home, either a callback is registered, or we do nothing. In both cases,
// we don't need to pass the leashes below.
if (activityRecord == null || task.getDisplayContent().getImeContainer().isVisible()
|| activityRecord.isActivityTypeHome()) {
- if (callback != null) {
+ if (applicationCallback != null) {
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
null /* topWindowLeash */, null /* screenshotSurface */,
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
null /* onBackNavigationDone */,
- callback /* onBackInvokedCallback */);
+ applicationCallback /* onBackInvokedCallback */);
} else {
return null;
}
@@ -159,12 +170,12 @@
prev = task.getActivity(
(r) -> !r.finishing && r.getTask() == task && !r.isTopRunningActivity());
- if (callback != null) {
+ if (applicationCallback != null) {
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
null /* topWindowLeash */, null /* screenshotSurface */,
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
null /* onBackNavigationDone */,
- callback /* onBackInvokedCallback */);
+ applicationCallback /* onBackInvokedCallback */);
} else if (prev != null) {
backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
} else if (task.returnsToHomeRootTask()) {
@@ -188,8 +199,8 @@
prevTaskId = prevTask != null ? prevTask.mTaskId : 0;
prevUserId = prevTask != null ? prevTask.mUserId : 0;
- ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s",
- prev != null ? prev.mActivityComponent : null);
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Activity is %s. "
+ + "Back type is %s", prev != null ? prev.mActivityComponent : null, backType);
//TODO(207481538) Remove once the infrastructure to support per-activity screenshot is
// implemented. For now we simply have the mBackScreenshots hash map that dumbly
@@ -204,6 +215,7 @@
return null;
}
// Prepare a leash to animate the current top window
+ // TODO(b/220934562): Use surface animator to better manage animation conflicts.
animLeash = removedWindowContainer.makeAnimationLeash()
.setName("BackPreview Leash for " + removedWindowContainer)
.setHidden(false)
@@ -231,12 +243,30 @@
activityRecord.windowType);
}
- SurfaceControl.Builder builder = new SurfaceControl.Builder()
+ screenshotSurface = new SurfaceControl.Builder()
.setName("BackPreview Screenshot for " + prev)
.setParent(animationLeashParent)
.setHidden(false)
- .setBLASTLayer();
- SurfaceControl screenshotSurface = builder.build();
+ .setBLASTLayer()
+ .build();
+ if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) {
+ task.mBackGestureStarted = true;
+ // Make launcher show from behind by marking its top activity as visible and
+ // launch-behind to bump its visibility for the duration of the back gesture.
+ prevTaskTopActivity = prevTask.getTopNonFinishingActivity();
+ if (prevTaskTopActivity != null) {
+ if (!prevTaskTopActivity.mVisibleRequested) {
+ prevTaskTopActivity.setVisibility(true);
+ }
+ prevTaskTopActivity.mLaunchTaskBehind = true;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to true. Activity=%s",
+ prevTaskTopActivity);
+ prevTaskTopActivity.mRootWindowContainer.ensureActivitiesVisible(
+ null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */);
+ }
+ }
// Find a screenshot of the previous activity
@@ -253,17 +283,20 @@
WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer;
try {
- activityRecord.token.linkToDeath(
- () -> resetSurfaces(finalRemovedWindowContainer), 0);
+ activityRecord.token.linkToDeath(() -> resetSurfaces(finalRemovedWindowContainer), 0);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to link to death", e);
resetSurfaces(removedWindowContainer);
return null;
}
- RemoteCallback onBackNavigationDone = new RemoteCallback(
- result -> resetSurfaces(finalRemovedWindowContainer
- ));
+ int finalBackType = backType;
+ final IOnBackInvokedCallback callback =
+ applicationCallback != null ? applicationCallback : systemCallback;
+ ActivityRecord finalPrevTaskTopActivity = prevTaskTopActivity;
+ RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone(
+ result, finalRemovedWindowContainer, finalBackType, task,
+ finalPrevTaskTopActivity));
return new BackNavigationInfo(backType,
topAppTarget,
screenshotSurface,
@@ -273,6 +306,39 @@
callback);
}
+ private void onBackNavigationDone(
+ Bundle result, WindowContainer windowContainer, int backType,
+ Task task, ActivityRecord prevTaskTopActivity) {
+ SurfaceControl surfaceControl = windowContainer.getSurfaceControl();
+ boolean triggerBack = result != null
+ ? result.getBoolean(BackNavigationInfo.KEY_TRIGGER_BACK)
+ : false;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, "
+ + "task=%s, prevTaskTopActivity=%s", backType, task, prevTaskTopActivity);
+
+ if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) {
+ if (triggerBack) {
+ if (surfaceControl != null && surfaceControl.isValid()) {
+ // When going back to home, hide the task surface before it is re-parented to
+ // avoid flicker.
+ SurfaceControl.Transaction t = windowContainer.getSyncTransaction();
+ t.hide(surfaceControl);
+ t.apply();
+ }
+ }
+ if (prevTaskTopActivity != null && !triggerBack) {
+ // Restore the launch-behind state.
+ task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevTaskTopActivity.token);
+ prevTaskTopActivity.mLaunchTaskBehind = false;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+ prevTaskTopActivity);
+ }
+ } else {
+ task.mBackGestureStarted = false;
+ }
+ resetSurfaces(windowContainer);
+ }
private HardwareBuffer getActivitySnapshot(@NonNull Task task,
ComponentName activityComponent) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 0c609191..9ad25ac8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -232,14 +232,14 @@
int requestedWidth, int requestedHeight, int viewFlags, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
- InsetsSourceControl[] outActiveControls) {
+ InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {
if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
+ Binder.getCallingPid());
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
int res = mService.relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
- outActiveControls);
+ outActiveControls, outSyncSeqIdBundle);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
+ Binder.getCallingPid());
@@ -265,9 +265,9 @@
@Override
public void finishDrawing(IWindow window,
- @Nullable SurfaceControl.Transaction postDrawTransaction) {
+ @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window);
- mService.finishDrawingWindow(this, window, postDrawTransaction);
+ mService.finishDrawingWindow(this, window, postDrawTransaction, seqId);
}
@Override
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cd7ebe3..dd4dd5f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -72,6 +72,7 @@
import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
@@ -609,6 +610,12 @@
boolean mLastSurfaceShowing = true;
+ /**
+ * Tracks if a back gesture is in progress.
+ * Skips any system transition animations if this is set to {@code true}.
+ */
+ boolean mBackGestureStarted = false;
+
private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
Intent _affinityIntent, String _affinity, String _rootAffinity,
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
@@ -3322,6 +3329,14 @@
}
});
}
+ } else if (mBackGestureStarted) {
+ // Cancel playing transitions if a back navigation animation is in progress.
+ // This bit is set by {@link BackNavigationController} when a back gesture is started.
+ // It is used as a one-off transition overwrite that is cleared when the back gesture
+ // is committed and triggers a transition, or when the gesture is cancelled.
+ mBackGestureStarted = false;
+ mDisplayContent.mSkipAppTransitionAnimation = true;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Skipping app transition animation. task=%s", this);
} else {
super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6718235..57b5ddb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2192,7 +2192,7 @@
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
- InsetsSourceControl[] outActiveControls) {
+ InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) {
Arrays.fill(outActiveControls, null);
int result = 0;
boolean configChanged;
@@ -2617,7 +2617,7 @@
}
void finishDrawingWindow(Session session, IWindow client,
- @Nullable SurfaceControl.Transaction postDrawTransaction) {
+ @Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
if (postDrawTransaction != null) {
postDrawTransaction.sanitize();
}
@@ -2628,7 +2628,7 @@
WindowState win = windowForClientLocked(session, client, false);
ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",
win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
- if (win != null && win.finishDrawing(postDrawTransaction)) {
+ if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
if (win.hasWallpaper()) {
win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index db687f6..50ae69a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3946,7 +3946,7 @@
try {
mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration,
- forceRelayout, alwaysConsumeSystemBars, displayId);
+ forceRelayout, alwaysConsumeSystemBars, displayId, Integer.MAX_VALUE);
if (drawPending && reportOrientation && mOrientationChanging) {
mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
ProtoLog.v(WM_DEBUG_ORIENTATION,
@@ -5938,7 +5938,7 @@
super.finishSync(outMergedTransaction, cancel);
}
- boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction) {
+ boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
if (mOrientationChangeRedrawRequestTime > 0) {
final long duration =
SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime;
@@ -5985,7 +5985,7 @@
void immediatelyNotifyBlastSync() {
prepareDrawHandlers();
- finishDrawing(null);
+ finishDrawing(null, Integer.MAX_VALUE);
mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
if (!useBLASTSync()) return;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index f05658b..e096687 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -494,9 +494,9 @@
final ArgumentCaptor<AlarmManagerService.UninstallReceiver> packageReceiverCaptor =
ArgumentCaptor.forClass(AlarmManagerService.UninstallReceiver.class);
- verify(mMockContext).registerReceiver(packageReceiverCaptor.capture(),
+ verify(mMockContext).registerReceiverForAllUsers(packageReceiverCaptor.capture(),
argThat((filter) -> filter.hasAction(Intent.ACTION_PACKAGE_ADDED)
- && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)));
+ && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)), isNull(), isNull());
mPackageChangesReceiver = packageReceiverCaptor.getValue();
assertEquals(mService.mExactAlarmCandidates, Collections.emptySet());
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
index 41d46f2..534d0a1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java
@@ -21,7 +21,6 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import android.app.AlarmManager;
import android.content.Context;
@@ -71,10 +70,10 @@
.strictness(Strictness.LENIENT)
.mockStatic(LocalServices.class)
.startMocking();
- when(mIrs.getContext()).thenReturn(mContext);
- when(mIrs.getCompleteEconomicPolicyLocked()).thenReturn(mEconomicPolicy);
- when(mIrs.getLock()).thenReturn(mIrs);
- when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mock(AlarmManager.class));
+ doReturn(mContext).when(mIrs).getContext();
+ doReturn(mEconomicPolicy).when(mIrs).getCompleteEconomicPolicyLocked();
+ doReturn(mIrs).when(mIrs).getLock();
+ doReturn(mock(AlarmManager.class)).when(mContext).getSystemService(Context.ALARM_SERVICE);
mScribe = new MockScribe(mIrs);
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 1f016fb..56c5150 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -28,6 +28,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -61,10 +63,12 @@
import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.TestUtils;
+import com.android.internal.compat.IPlatformCompat;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService.AccessibilityDisplayListener;
import com.android.server.accessibility.magnification.FullScreenMagnificationController;
import com.android.server.accessibility.magnification.MagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.accessibility.magnification.WindowMagnificationManager;
import com.android.server.accessibility.test.MessageCapturingHandler;
import com.android.server.pm.UserManagerInternal;
@@ -185,7 +189,7 @@
mA11yms.mUserStates.put(mA11yms.getCurrentUserIdLocked(), userState);
}
- private void setupAccessibilityServiceConnection() {
+ private void setupAccessibilityServiceConnection(int serviceInfoFlag) {
final AccessibilityUserState userState = mA11yms.mUserStates.get(
mA11yms.getCurrentUserIdLocked());
when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
@@ -193,7 +197,12 @@
mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class);
when(mMockBinder.queryLocalInterface(any())).thenReturn(mMockServiceClient);
+ when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mock(KeyEventDispatcher.class));
+ when(mMockSystemSupport.getMagnificationProcessor()).thenReturn(
+ mock(MagnificationProcessor.class));
mTestableContext.addMockService(COMPONENT_NAME, mMockBinder);
+
+ mMockServiceInfo.flags = serviceInfoFlag;
mAccessibilityServiceConnection = new AccessibilityServiceConnection(
userState,
mTestableContext,
@@ -256,7 +265,7 @@
@SmallTest
@Test
public void testOnSystemActionsChanged() throws Exception {
- setupAccessibilityServiceConnection();
+ setupAccessibilityServiceConnection(0);
final AccessibilityUserState userState = mA11yms.mUserStates.get(
mA11yms.getCurrentUserIdLocked());
@@ -376,7 +385,7 @@
@SmallTest
@Test
public void testOnClientChange_boundServiceCanControlMagnification_requestConnection() {
- setupAccessibilityServiceConnection();
+ setupAccessibilityServiceConnection(0);
when(mMockSecurityPolicy.canControlMagnification(any())).thenReturn(true);
// Invokes client change to trigger onUserStateChanged.
@@ -385,6 +394,29 @@
verify(mMockWindowMagnificationMgr).requestConnection(true);
}
+ @Test
+ public void testUnbindIme_whenServiceUnbinds() {
+ setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR);
+ mAccessibilityServiceConnection.unbindLocked();
+ verify(mMockSystemSupport, atLeastOnce()).unbindImeLocked(mAccessibilityServiceConnection);
+ }
+
+ @Test
+ public void testUnbindIme_whenServiceCrashed() {
+ setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR);
+ mAccessibilityServiceConnection.binderDied();
+ verify(mMockSystemSupport).unbindImeLocked(mAccessibilityServiceConnection);
+ }
+
+ @Test
+ public void testUnbindIme_whenServiceStopsRequestingIme() {
+ setupAccessibilityServiceConnection(AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR);
+ doCallRealMethod().when(mMockServiceInfo).updateDynamicallyConfigurableProperties(
+ any(IPlatformCompat.class), any(AccessibilityServiceInfo.class));
+ mAccessibilityServiceConnection.setServiceInfo(new AccessibilityServiceInfo());
+ verify(mMockSystemSupport).unbindImeLocked(mAccessibilityServiceConnection);
+ }
+
public static class FakeInputFilter extends AccessibilityInputFilter {
FakeInputFilter(Context context,
AccessibilityManagerService service) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index c7b5547..06b7112 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -316,7 +316,8 @@
asHandle(currentUser));
try {
assertThat(mUserManager.removeUserWhenPossible(user1.getUserHandle(),
- /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
+ /* overrideDevicePolicy= */ false))
+ .isEqualTo(UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION);
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false,
asHandle(currentUser));
@@ -353,7 +354,8 @@
@Test
public void testRemoveUserWhenPossible_systemUserReturnsError() throws Exception {
assertThat(mUserManager.removeUserWhenPossible(UserHandle.SYSTEM,
- /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
+ /* overrideDevicePolicy= */ false))
+ .isEqualTo(UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER);
assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue();
}
@@ -363,7 +365,8 @@
public void testRemoveUserWhenPossible_invalidUserReturnsError() throws Exception {
assertThat(hasUser(Integer.MAX_VALUE)).isFalse();
assertThat(mUserManager.removeUserWhenPossible(UserHandle.of(Integer.MAX_VALUE),
- /* overrideDevicePolicy= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
+ /* overrideDevicePolicy= */ false))
+ .isEqualTo(UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND);
}
@MediumTest
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index c21a5b6..92550a3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -30,7 +30,10 @@
import android.annotation.NonNull;
import android.hardware.HardwareBuffer;
import android.platform.test.annotations.Presubmit;
+import android.window.BackEvent;
import android.window.BackNavigationInfo;
+import android.window.IOnBackInvokedCallback;
+import android.window.OnBackInvokedDispatcher;
import android.window.TaskSnapshot;
import org.junit.Before;
@@ -42,15 +45,19 @@
public class BackNavigationControllerTests extends WindowTestsBase {
private BackNavigationController mBackNavigationController;
+ private IOnBackInvokedCallback mOnBackInvokedCallback;
@Before
public void setUp() throws Exception {
mBackNavigationController = new BackNavigationController();
+ mOnBackInvokedCallback = createBackCallback();
}
@Test
public void backTypeHomeWhenBackToLauncher() {
Task task = createTopTaskWithActivity();
+ registerSystemOnBackInvokedCallback();
+
BackNavigationInfo backNavigationInfo =
mBackNavigationController.startBackNavigation(task, new StubTransaction());
assertThat(backNavigationInfo).isNotNull();
@@ -63,6 +70,8 @@
Task taskA = createTask(mDefaultDisplay);
createActivityRecord(taskA);
Task task = createTopTaskWithActivity();
+ registerSystemOnBackInvokedCallback();
+
BackNavigationInfo backNavigationInfo =
mBackNavigationController.startBackNavigation(task, new StubTransaction());
assertThat(backNavigationInfo).isNotNull();
@@ -75,6 +84,8 @@
Task task = createTopTaskWithActivity();
mAtm.setFocusedTask(task.mTaskId,
createAppWindow(task, FIRST_APPLICATION_WINDOW, "window").mActivityRecord);
+ registerSystemOnBackInvokedCallback();
+
BackNavigationInfo backNavigationInfo =
mBackNavigationController.startBackNavigation(task, new StubTransaction());
assertThat(backNavigationInfo).isNotNull();
@@ -89,6 +100,7 @@
public void backNavInfoFullyPopulated() {
Task task = createTopTaskWithActivity();
createAppWindow(task, FIRST_APPLICATION_WINDOW, "window");
+ registerSystemOnBackInvokedCallback();
// We need a mock screenshot so
TaskSnapshotController taskSnapshotController = createMockTaskSnapshotController();
@@ -104,6 +116,30 @@
assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull();
}
+ @Test
+ public void preparesForBackToHome() {
+ Task task = createTopTaskWithActivity();
+ ActivityRecord activity = task.getTopActivity(false, false);
+ registerSystemOnBackInvokedCallback();
+
+ BackNavigationInfo backNavigationInfo =
+ mBackNavigationController.startBackNavigation(task, new StubTransaction());
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME));
+ }
+
+ @Test
+ public void backTypeCallback() {
+ Task task = createTopTaskWithActivity();
+ ActivityRecord activity = task.getTopActivity(false, false);
+ registerApplicationOnBackInvokedCallback();
+
+ BackNavigationInfo backNavigationInfo =
+ mBackNavigationController.startBackNavigation(task, new StubTransaction());
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+ }
+
@NonNull
private TaskSnapshotController createMockTaskSnapshotController() {
TaskSnapshotController taskSnapshotController = mock(TaskSnapshotController.class);
@@ -126,4 +162,30 @@
mAtm.setFocusedTask(task.mTaskId, record);
return task;
}
+
+ private void registerSystemOnBackInvokedCallback() {
+ mWm.getFocusedWindowLocked().setOnBackInvokedCallback(
+ mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_SYSTEM);
+ }
+
+ private void registerApplicationOnBackInvokedCallback() {
+ mWm.getFocusedWindowLocked().setOnBackInvokedCallback(
+ mOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
+ }
+
+ private IOnBackInvokedCallback createBackCallback() {
+ return new IOnBackInvokedCallback.Stub() {
+ @Override
+ public void onBackStarted() { }
+
+ @Override
+ public void onBackProgressed(BackEvent backEvent) { }
+
+ @Override
+ public void onBackCancelled() { }
+
+ @Override
+ public void onBackInvoked() { }
+ };
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index 7dfb5ae..4f35d55 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -44,7 +44,7 @@
@Override
public void resized(ClientWindowFrames frames, boolean reportDraw,
MergedConfiguration mergedConfig, boolean forceLayout, boolean alwaysConsumeSystemBars,
- int displayId) throws RemoteException {
+ int displayId, int seqId) throws RemoteException {
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index c4547f6..7e5d017 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -692,7 +692,8 @@
statusBar.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
final SurfaceControl.Transaction postDrawTransaction =
mock(SurfaceControl.Transaction.class);
- final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction);
+ final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction,
+ Integer.MAX_VALUE);
assertFalse(layoutNeeded);
transactionCommittedListener.onTransactionCommitted();
@@ -742,7 +743,7 @@
player.finish();
// The controller should be cleared if the target windows are drawn.
- statusBar.finishDrawing(mWm.mTransactionFactory.get());
+ statusBar.finishDrawing(mWm.mTransactionFactory.get(), Integer.MAX_VALUE);
statusBar.setOrientationChanging(false);
assertNull(mDisplayContent.getAsyncRotationController());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 6d7895f..6a3aa78 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -504,7 +504,7 @@
assertTrue(win.useBLASTSync());
final SurfaceControl.Transaction drawT = new StubTransaction();
win.prepareDrawHandlers();
- assertTrue(win.finishDrawing(drawT));
+ assertTrue(win.finishDrawing(drawT, Integer.MAX_VALUE));
assertEquals(drawT, handledT[0]);
assertFalse(win.useBLASTSync());
@@ -693,7 +693,7 @@
doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frames */,
anyBoolean() /* reportDraw */, any() /* mergedConfig */,
anyBoolean() /* forceLayout */, anyBoolean() /* alwaysConsumeSystemBars */,
- anyInt() /* displayId */);
+ anyInt() /* displayId */, anyInt() /* seqId */);
} catch (RemoteException ignored) {
}
win.reportResized();
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 3a3b363..d2a4c3e 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1090,6 +1090,13 @@
*/
public static final int NO_RETRY_FAILURE = 0x1000B;
+ /**
+ * Traffic descriptors in DataCallResponse is empty.
+ *
+ * @hide
+ */
+ public static final int NO_TRAFFIC_DESCRIPTORS = 0x1000C;
+
private static final Map<Integer, String> sFailCauseMap;
static {
sFailCauseMap = new HashMap<>();
@@ -1524,6 +1531,7 @@
sFailCauseMap.put(SERVICE_TEMPORARILY_UNAVAILABLE, "SERVICE_TEMPORARILY_UNAVAILABLE");
sFailCauseMap.put(REQUEST_NOT_SUPPORTED, "REQUEST_NOT_SUPPORTED");
sFailCauseMap.put(NO_RETRY_FAILURE, "NO_RETRY_FAILURE");
+ sFailCauseMap.put(NO_TRAFFIC_DESCRIPTORS, "NO_TRAFFIC_DESCRIPTORS");
}
private DataFailCause() {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5ef22de..3f430ab 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8352,24 +8352,6 @@
}
/**
- * Get P-CSCF address from PCO after data connection is established or modified.
- * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
- * @return array of P-CSCF address
- * @hide
- */
- public String[] getPcscfAddress(String apnType) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony == null)
- return new String[0];
- return telephony.getPcscfAddress(apnType, getOpPackageName(), getAttributionTag());
- } catch (RemoteException e) {
- return new String[0];
- }
- }
-
-
- /**
* Resets the {@link android.telephony.ims.ImsService} associated with the specified sim slot.
* Used by diagnostic apps to force the IMS stack to be disabled and re-enabled in an effort to
* recover from scenarios where the {@link android.telephony.ims.ImsService} gets in to a bad
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index dc96b35..a5e2c1f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -978,14 +978,6 @@
boolean isManualNetworkSelectionAllowed(int subId);
/**
- * Get P-CSCF address from PCO after data connection is established or modified.
- * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
- * @param callingPackage The package making the call.
- * @param callingFeatureId The feature in the package.
- */
- String[] getPcscfAddress(String apnType, String callingPackage, String callingFeatureId);
-
- /**
* Set IMS registration state
*/
void setImsRegistrationState(boolean registered);
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
index 0423b7a..ff24d16 100644
--- a/tools/validatekeymaps/Android.bp
+++ b/tools/validatekeymaps/Android.bp
@@ -32,7 +32,7 @@
"libui-types",
],
target: {
- linux_glibc: {
+ host_linux: {
static_libs: [
// libbinder is only available for linux
"libbinder",