Merge "Show the UMO in the hub mode UI" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 14869db..323f9e9 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -4464,6 +4464,7 @@
method public boolean onPreparePanel(int, @Nullable android.view.View, @NonNull android.view.Menu);
method public void onProvideAssistContent(android.app.assist.AssistContent);
method public void onProvideAssistData(android.os.Bundle);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu, int);
method public android.net.Uri onProvideReferrer();
method public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[]);
method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[], int);
@@ -13973,6 +13974,7 @@
method public String getColumnName(int);
method public android.os.Bundle getExtras();
method public android.net.Uri getNotificationUri();
+ method public java.util.List<android.net.Uri> getNotificationUris();
method public final int getPosition();
method public int getType(int);
method @Deprecated protected Object getUpdatedField(int);
@@ -13998,6 +14000,7 @@
method public android.os.Bundle respond(android.os.Bundle);
method public void setExtras(android.os.Bundle);
method public void setNotificationUri(android.content.ContentResolver, android.net.Uri);
+ method public void setNotificationUris(@NonNull android.content.ContentResolver, @NonNull java.util.List<android.net.Uri>);
method public void unregisterContentObserver(android.database.ContentObserver);
method public void unregisterDataSetObserver(android.database.DataSetObserver);
field @Deprecated protected boolean mClosed;
@@ -14129,6 +14132,7 @@
method public boolean hasNext();
method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
method public android.database.CursorJoiner.Result next();
+ method public void remove();
}
public enum CursorJoiner.Result {
@@ -14196,6 +14200,7 @@
method public int getInt(int);
method public long getLong(int);
method public android.net.Uri getNotificationUri();
+ method public java.util.List<android.net.Uri> getNotificationUris();
method public int getPosition();
method public short getShort(int);
method public String getString(int);
@@ -14220,6 +14225,7 @@
method public android.os.Bundle respond(android.os.Bundle);
method public void setExtras(android.os.Bundle);
method public void setNotificationUri(android.content.ContentResolver, android.net.Uri);
+ method public void setNotificationUris(android.content.ContentResolver, java.util.List<android.net.Uri>);
method public void unregisterContentObserver(android.database.ContentObserver);
method public void unregisterDataSetObserver(android.database.DataSetObserver);
}
@@ -22213,6 +22219,9 @@
ctor public MediaCodec.CryptoException(int, @Nullable String);
method @Nullable public android.media.MediaCodec.CryptoInfo getCryptoInfo();
method public int getErrorCode();
+ method public int getErrorContext();
+ method public int getOemError();
+ method public int getVendorError();
field @Deprecated public static final int ERROR_FRAME_TOO_LARGE = 8; // 0x8
field @Deprecated public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4
field @Deprecated public static final int ERROR_INSUFFICIENT_SECURITY = 7; // 0x7
@@ -22725,6 +22734,9 @@
public final class MediaCryptoException extends java.lang.Exception implements android.media.MediaDrmThrowable {
ctor public MediaCryptoException(@Nullable String);
+ method public int getErrorContext();
+ method public int getOemError();
+ method public int getVendorError();
}
public abstract class MediaDataSource implements java.io.Closeable {
@@ -22949,6 +22961,9 @@
public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException implements android.media.MediaDrmThrowable {
method @NonNull public String getDiagnosticInfo();
method public int getErrorCode();
+ method public int getErrorContext();
+ method public int getOemError();
+ method public int getVendorError();
method public boolean isTransient();
}
@@ -23022,6 +23037,9 @@
public static final class MediaDrm.SessionException extends java.lang.RuntimeException implements android.media.MediaDrmThrowable {
ctor public MediaDrm.SessionException(int, @Nullable String);
method @Deprecated public int getErrorCode();
+ method public int getErrorContext();
+ method public int getOemError();
+ method public int getVendorError();
method public boolean isTransient();
field @Deprecated public static final int ERROR_RESOURCE_CONTENTION = 1; // 0x1
field @Deprecated public static final int ERROR_UNKNOWN = 0; // 0x0
@@ -23029,6 +23047,9 @@
public class MediaDrmException extends java.lang.Exception implements android.media.MediaDrmThrowable {
ctor public MediaDrmException(String);
+ method public int getErrorContext();
+ method public int getOemError();
+ method public int getVendorError();
}
public class MediaDrmResetException extends java.lang.IllegalStateException implements android.media.MediaDrmThrowable {
@@ -31918,6 +31939,7 @@
method public void surfaceCreated(android.view.SurfaceHolder);
method public void surfaceDestroyed(android.view.SurfaceHolder);
method @Deprecated public void surfaceRedrawNeeded(android.view.SurfaceHolder);
+ method public void surfaceRedrawNeededAsync(android.view.SurfaceHolder, Runnable);
field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1
field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2
field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1
@@ -47459,6 +47481,7 @@
method public boolean hasNext();
method public java.util.Iterator<java.lang.String> iterator();
method public String next();
+ method public void remove();
method public void setString(String);
}
@@ -48924,6 +48947,7 @@
method public void ensureCapacity(int);
method public java.util.Set<java.util.Map.Entry<K,V>> entrySet();
method public boolean equals(@Nullable Object);
+ method public void forEach(java.util.function.BiConsumer<? super K,? super V>);
method public V get(Object);
method public int hashCode();
method public int indexOfKey(Object);
@@ -48937,6 +48961,7 @@
method public V remove(Object);
method public boolean removeAll(java.util.Collection<?>);
method public V removeAt(int);
+ method public void replaceAll(java.util.function.BiFunction<? super K,? super V,? extends V>);
method public boolean retainAll(java.util.Collection<?>);
method public V setValueAt(int, V);
method public int size();
@@ -48967,6 +48992,7 @@
method public boolean removeAll(android.util.ArraySet<? extends E>);
method public boolean removeAll(java.util.Collection<?>);
method public E removeAt(int);
+ method public boolean removeIf(java.util.function.Predicate<? super E>);
method public boolean retainAll(java.util.Collection<?>);
method public int size();
method public Object[] toArray();
@@ -52834,6 +52860,7 @@
method protected void dispatchThawSelfOnly(android.util.SparseArray<android.os.Parcelable>);
method protected boolean drawChild(@NonNull android.graphics.Canvas, android.view.View, long);
method public void endViewTransition(android.view.View);
+ method @Nullable public android.window.OnBackInvokedDispatcher findOnBackInvokedDispatcherForChild(@NonNull android.view.View, @NonNull android.view.View);
method public android.view.View focusSearch(android.view.View, int);
method public void focusableViewAvailable(android.view.View);
method protected android.view.ViewGroup.LayoutParams generateDefaultLayoutParams();
@@ -52875,6 +52902,7 @@
method public void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
method public final void offsetDescendantRectToMyCoords(android.view.View, android.graphics.Rect);
method public final void offsetRectIntoDescendantCoords(android.view.View, android.graphics.Rect);
+ method @CallSuper public void onDescendantInvalidated(@NonNull android.view.View, @NonNull android.view.View);
method public boolean onInterceptHoverEvent(android.view.MotionEvent);
method public boolean onInterceptTouchEvent(android.view.MotionEvent);
method protected abstract void onLayout(boolean, int, int, int, int);
@@ -55058,12 +55086,14 @@
method @Nullable public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
method @Nullable public android.os.Handler getHandler();
method @Nullable public CharSequence getSelectedText(int);
+ method @Nullable public android.view.inputmethod.SurroundingText getSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(String, android.os.Bundle);
method public static final void removeComposingSpans(@NonNull android.text.Spannable);
+ method public boolean replaceText(@IntRange(from=0) int, @IntRange(from=0) int, @NonNull CharSequence, int, @Nullable android.view.inputmethod.TextAttribute);
method public boolean reportFullscreenMode(boolean);
method public boolean requestCursorUpdates(int);
method public boolean sendKeyEvent(android.view.KeyEvent);
@@ -55071,6 +55101,7 @@
method public static void setComposingSpans(@NonNull android.text.Spannable);
method public boolean setComposingText(CharSequence, int);
method public boolean setSelection(int, int);
+ method @Nullable public android.view.inputmethod.TextSnapshot takeSnapshot();
}
public final class CompletionInfo implements android.os.Parcelable {
@@ -55407,6 +55438,7 @@
method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public boolean commitText(CharSequence, int);
+ method public boolean commitText(@NonNull CharSequence, int, @Nullable android.view.inputmethod.TextAttribute);
method public boolean deleteSurroundingText(int, int);
method public boolean deleteSurroundingTextInCodePoints(int, int);
method public boolean endBatchEdit();
@@ -55415,18 +55447,29 @@
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
method public android.os.Handler getHandler();
method public CharSequence getSelectedText(int);
+ method @Nullable public android.view.inputmethod.SurroundingText getSurroundingText(int, int, int);
method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
+ method public void performHandwritingGesture(@NonNull android.view.inputmethod.HandwritingGesture, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.IntConsumer);
method public boolean performPrivateCommand(String, android.os.Bundle);
+ method public boolean performSpellCheck();
+ method public boolean previewHandwritingGesture(@NonNull android.view.inputmethod.PreviewableHandwritingGesture, @Nullable android.os.CancellationSignal);
+ method public boolean replaceText(@IntRange(from=0) int, @IntRange(from=0) int, @NonNull CharSequence, int, @Nullable android.view.inputmethod.TextAttribute);
method public boolean reportFullscreenMode(boolean);
method public boolean requestCursorUpdates(int);
+ method public boolean requestCursorUpdates(int, int);
+ method public void requestTextBoundsInfo(@NonNull android.graphics.RectF, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.inputmethod.TextBoundsInfoResult>);
method public boolean sendKeyEvent(android.view.KeyEvent);
method public boolean setComposingRegion(int, int);
+ method public boolean setComposingRegion(int, int, @Nullable android.view.inputmethod.TextAttribute);
method public boolean setComposingText(CharSequence, int);
+ method public boolean setComposingText(@NonNull CharSequence, int, @Nullable android.view.inputmethod.TextAttribute);
+ method public boolean setImeConsumesInput(boolean);
method public boolean setSelection(int, int);
method public void setTarget(android.view.inputmethod.InputConnection);
+ method @Nullable public android.view.inputmethod.TextSnapshot takeSnapshot();
}
public final class InputContentInfo implements android.os.Parcelable {
@@ -57993,6 +58036,7 @@
public abstract class BaseAdapter implements android.widget.ListAdapter android.widget.SpinnerAdapter {
ctor public BaseAdapter();
method public boolean areAllItemsEnabled();
+ method public CharSequence[] getAutofillOptions();
method public android.view.View getDropDownView(int, android.view.View, android.view.ViewGroup);
method public int getItemViewType(int);
method public int getViewTypeCount();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index b5e9407..eefa36e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10228,6 +10228,7 @@
ctor public ParcelableHolder(int);
method public int describeContents();
method @Nullable public <T extends android.os.Parcelable> T getParcelable(@NonNull Class<T>);
+ method public int getStability();
method public void readFromParcel(@NonNull android.os.Parcel);
method public void setParcelable(@Nullable android.os.Parcelable);
method public void writeToParcel(@NonNull android.os.Parcel, int);
diff --git a/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
index 6b78d05..5c5083a 100644
--- a/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
+++ b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
@@ -6,3 +6,10 @@
description: "Enable USB data compliance warnings when set"
bug: "296119135"
}
+
+flag {
+ name: "enable_input_power_limited_warning"
+ namespace: "system_sw_usb"
+ description: "Flag incompatible charging on COMPLIANCE_WARNING_INPUT_POWER_LIMITED instead of COMPLIANCE_WARNING_OTHER when enabled"
+ bug: "308700954"
+}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 3795fc8..440a332 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -43,7 +43,10 @@
"-Wall",
"-Werror",
+ "-Wextra",
+ "-Wthread-safety",
"-Wno-error=deprecated-declarations",
+ "-Wno-unused-parameter",
"-Wunused",
"-Wunreachable-code",
diff --git a/core/jni/android_content_res_ResourceTimer.cpp b/core/jni/android_content_res_ResourceTimer.cpp
index 91e3c921..66bda61 100644
--- a/core/jni/android_content_res_ResourceTimer.cpp
+++ b/core/jni/android_content_res_ResourceTimer.cpp
@@ -44,9 +44,9 @@
static int NativeGetTimers(JNIEnv* env, jobject /*clazz*/, jobjectArray timer, jboolean reset) {
size_t size = ResourceTimer::counterSize;
- if (jsize st = env->GetArrayLength(timer); st < size) {
- // Shrink the size to the minimum of the available counters and the available space.
- size = st;
+ if (size_t st = env->GetArrayLength(timer); st < size) {
+ // Shrink the size to the minimum of the available counters and the available space.
+ size = st;
}
for (size_t i = 0; i < size; i++) {
ResourceTimer::Timer src;
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 30e546c..82570be8 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -1892,8 +1892,8 @@
camera_metadata_entry entry =
results.find(ANDROID_SENSOR_NOISE_PROFILE);
- const status_t numPlaneColors = isBayer ? 3 : 1;
- const status_t numCfaChannels = isBayer ? 4 : 1;
+ const unsigned long numPlaneColors = isBayer ? 3 : 1;
+ const unsigned long numCfaChannels = isBayer ? 4 : 1;
uint8_t cfaOut[numCfaChannels];
if ((err = convertCFA(cfaEnum, /*out*/cfaOut)) != OK) {
diff --git a/core/jni/android_hardware_camera2_impl_CameraExtensionJpegProcessor.cpp b/core/jni/android_hardware_camera2_impl_CameraExtensionJpegProcessor.cpp
index 1390759..4bde87f 100644
--- a/core/jni/android_hardware_camera2_impl_CameraExtensionJpegProcessor.cpp
+++ b/core/jni/android_hardware_camera2_impl_CameraExtensionJpegProcessor.cpp
@@ -599,7 +599,7 @@
quality, cropLeft, cropTop, cropRight, cropBottom, rot90);
size_t finalJpegSize = actualJpegSize + sizeof(CameraBlob);
- if (finalJpegSize > outBufCapacity) {
+ if (finalJpegSize > static_cast<size_t>(outBufCapacity)) {
ALOGE("%s: Final jpeg buffer %zu not large enough for the jpeg blob header with "\
"capacity %d", __FUNCTION__, finalJpegSize, outBufCapacity);
return actualJpegSize;
diff --git a/core/jni/android_media_AudioProductStrategies.cpp b/core/jni/android_media_AudioProductStrategies.cpp
index 4b563d7..7c9dae0 100644
--- a/core/jni/android_media_AudioProductStrategies.cpp
+++ b/core/jni/android_media_AudioProductStrategies.cpp
@@ -88,12 +88,12 @@
int attrGroupIndex = 0;
std::map<int /**attributesGroupIndex*/, std::vector<VolumeGroupAttributes> > groups;
for (const auto &attr : strategy.getVolumeGroupAttributes()) {
- int groupId = attr.getGroupId();
+ auto groupId = attr.getGroupId();
int streamType = attr.getStreamType();
const auto &iter = std::find_if(begin(groups), end(groups),
[groupId, streamType](const auto &iter) {
const auto &frontAttr = iter.second.front();
- return frontAttr.getGroupId() == groupId && frontAttr.getStreamType() == streamType;
+ return (frontAttr.getGroupId() == groupId && frontAttr.getStreamType() == streamType);
});
// Same Volume Group Id and same stream type
if (iter != end(groups)) {
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 6440cc3..3413ede 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2501,7 +2501,7 @@
int *nativeArray = nullptr;
nativeArray = env->GetIntArrayElements(jArray, 0);
if (nativeArray != nullptr) {
- for (size_t i = 0; i < len; i++) {
+ for (size_t i = 0; i < static_cast<size_t>(len); i++) {
nativeVector.push_back(nativeArray[i]);
}
env->ReleaseIntArrayElements(jArray, nativeArray, 0);
@@ -2565,7 +2565,7 @@
if (nativeSystemUsages != nullptr) {
jsize len = env->GetArrayLength(systemUsages);
- for (size_t i = 0; i < len; i++) {
+ for (size_t i = 0; i < static_cast<size_t>(len); i++) {
audio_usage_t nativeAudioUsage =
static_cast<audio_usage_t>(nativeSystemUsages[i]);
nativeSystemUsagesVector.push_back(nativeAudioUsage);
@@ -2776,7 +2776,7 @@
return jStatus;
}
- if (devices.size() > maxResultSize) {
+ if (devices.size() > static_cast<size_t>(maxResultSize)) {
return AUDIO_JAVA_INVALID_OPERATION;
}
size_t index = 0;
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index 9bd0700..47b4a46 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -221,7 +221,7 @@
ssize_t rc = SendFileDescriptorVector(fd, buffer, len, fds);
- while (rc != len) {
+ while (rc != static_cast<ssize_t>(len)) {
if (rc == -1) {
jniThrowIOException(env, errno);
return -1;
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index a9db91b..e554b44 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -265,7 +265,7 @@
// justify passing such a large amount of data over this path. So the
// alternative (updating the constructor and other code to accept other
// types, should also probably not be taken in this case).
- CHECK_LE(size, std::numeric_limits<jint>::max());
+ CHECK_LE(size, static_cast<size_t>(std::numeric_limits<jint>::max()));
return env->NewObject(clazz.get(), constructID, static_cast<jint>(size));
}
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 4d8dac1..3539476 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -691,7 +691,7 @@
// String tries to allocate itself on the stack, within a known size, but will
// make a heap allocation if not.
-template <size_t StackReserve>
+template <jsize StackReserve>
class StackString {
public:
StackString(JNIEnv* env, jstring str) : mEnv(env), mJStr(str) {
diff --git a/core/jni/android_os_PerformanceHintManager.cpp b/core/jni/android_os_PerformanceHintManager.cpp
index 27c4cd4..95bf49f 100644
--- a/core/jni/android_os_PerformanceHintManager.cpp
+++ b/core/jni/android_os_PerformanceHintManager.cpp
@@ -224,7 +224,7 @@
return nullptr;
}
jint* threadIds = env->GetIntArrayElements(jintArr, 0);
- for (int i = 0; i < size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
threadIds[i] = tidsVector[i];
}
env->ReleaseIntArrayElements(jintArr, threadIds, 0);
diff --git a/core/jni/android_util_CharsetUtils.cpp b/core/jni/android_util_CharsetUtils.cpp
index 7ab6e8f2..7071cf2 100644
--- a/core/jni/android_util_CharsetUtils.cpp
+++ b/core/jni/android_util_CharsetUtils.cpp
@@ -25,7 +25,7 @@
// Quickly check if destination has plenty of room for worst-case
// 4-bytes-per-char encoded size
- const size_t worstLen = (srcLen * 4);
+ const jint worstLen = (srcLen * 4);
if (destOff >= 0 && destOff + worstLen < destLen) {
env->GetStringUTFRegion(src, 0, srcLen, destPtr + destOff);
return strlen(destPtr + destOff + srcLen) + srcLen;
@@ -33,7 +33,7 @@
// String still might fit in destination, but we need to measure
// its actual encoded size to be sure
- const size_t encodedLen = env->GetStringUTFLength(src);
+ const jint encodedLen = env->GetStringUTFLength(src);
if (destOff >= 0 && destOff + encodedLen < destLen) {
env->GetStringUTFRegion(src, 0, srcLen, destPtr + destOff);
return encodedLen;
diff --git a/core/jni/android_util_FileObserver.cpp b/core/jni/android_util_FileObserver.cpp
index c64c212..8d3da7b 100644
--- a/core/jni/android_util_FileObserver.cpp
+++ b/core/jni/android_util_FileObserver.cpp
@@ -114,7 +114,7 @@
if (fd >= 0)
{
size_t count = wfds.size();
- for (jsize i = 0; i < count; ++i) {
+ for (size_t i = 0; i < count; ++i) {
jstring pathString = (jstring) env->GetObjectArrayElement(pathStrings, i);
ScopedUtfChars path(env, pathString);
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 41c65ae..fef8ad7 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -140,7 +140,7 @@
env->ExceptionClear();
return NULL;
}
- for (int i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
+ for (size_t i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
VsyncEventData::FrameTimeline frameTimeline = vsyncEventData.frameTimelines[i];
ScopedLocalRef<jobject>
frameTimelineObj(env,
@@ -193,7 +193,7 @@
gDisplayEventReceiverClassInfo
.vsyncEventDataClassInfo
.frameTimelines)));
- for (int i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
+ for (size_t i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
VsyncEventData::FrameTimeline& frameTimeline = vsyncEventData.frameTimelines[i];
ScopedLocalRef<jobject>
frameTimelineObj(env, env->GetObjectArrayElement(frameTimelinesObj.get(), i));
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 9833598..a800e6e 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1950,7 +1950,7 @@
jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(),
gJankDataClassInfo.clazz, nullptr);
- for (int i = 0; i < jankData.size(); i++) {
+ for (size_t i = 0; i < jankData.size(); i++) {
jobject jJankData = env->NewObject(gJankDataClassInfo.clazz,
gJankDataClassInfo.ctor, jankData[i].frameVsyncId, jankData[i].jankType);
env->SetObjectArrayElement(jJankDataArray, i, jJankData);
diff --git a/core/jni/android_window_WindowInfosListener.cpp b/core/jni/android_window_WindowInfosListener.cpp
index 55995df..bc69d1e6 100644
--- a/core/jni/android_window_WindowInfosListener.cpp
+++ b/core/jni/android_window_WindowInfosListener.cpp
@@ -67,7 +67,7 @@
static jobjectArray fromWindowInfos(JNIEnv* env, const std::vector<WindowInfo>& windowInfos) {
jobjectArray jWindowHandlesArray =
env->NewObjectArray(windowInfos.size(), gInputWindowHandleClass, nullptr);
- for (int i = 0; i < windowInfos.size(); i++) {
+ for (size_t i = 0; i < windowInfos.size(); i++) {
ScopedLocalRef<jobject>
jWindowHandle(env,
android_view_InputWindowHandle_fromWindowInfo(env, windowInfos[i]));
@@ -80,7 +80,7 @@
static jobjectArray fromDisplayInfos(JNIEnv* env, const std::vector<DisplayInfo>& displayInfos) {
jobjectArray jDisplayInfoArray =
env->NewObjectArray(displayInfos.size(), gDisplayInfoClassInfo.clazz, nullptr);
- for (int i = 0; i < displayInfos.size(); i++) {
+ for (size_t i = 0; i < displayInfos.size(); i++) {
ScopedLocalRef<jobject> jDisplayInfo(env, fromDisplayInfo(env, displayInfos[i]));
env->SetObjectArrayElement(jDisplayInfoArray, i, jDisplayInfo.get());
}
diff --git a/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp b/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp
index d4f6e18..0c39a69 100644
--- a/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp
+++ b/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp
@@ -266,11 +266,11 @@
auto jsResourceName = reinterpret_cast<jstring>(
env->GetObjectField(entry, gFabricatedOverlayInternalEntryOffsets.resourceName));
const ScopedUtfChars resourceName(env, jsResourceName);
- const auto dataType =
+ const jint dataType =
env->GetIntField(entry, gFabricatedOverlayInternalEntryOffsets.dataType);
// In Java, the data type is int but the maximum value of data Type is less than 0xff.
- if (dataType >= UCHAR_MAX) {
+ if (dataType >= static_cast<jint>(UCHAR_MAX)) {
jniThrowException(env, IllegalArgumentException, "Unsupported data type");
return;
}
diff --git a/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
index 098a4d8..cf70c90 100644
--- a/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
+++ b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
@@ -55,7 +55,7 @@
static jboolean KernelCpuUidFreqTimeBpfMapReader_removeUidRange(JNIEnv *env, jclass, jint startUid,
jint endUid) {
- for (uint32_t uid = startUid; uid <= endUid; ++uid) {
+ for (jint uid = startUid; uid <= endUid; ++uid) {
if (!android::bpf::clearUidTimes(uid)) return false;
}
return true;
diff --git a/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp b/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp
index dfae684..be9013b 100644
--- a/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp
+++ b/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp
@@ -147,7 +147,7 @@
std::unique_ptr<ICpuTimeInStateReader> cpuTimeInStateReader(
getCpuTimeInStateReader(env, cpuTimeInStateReaderObject));
- for (int i = 0; i < selectedThreadIds.size(); i++) {
+ for (size_t i = 0; i < selectedThreadIds.size(); i++) {
if (!cpuTimeInStateReader->startAggregatingTaskCpuTimes(selectedThreadIds[i],
SELECTED_THREAD_AGGREGATION_KEY)) {
return false;
@@ -312,11 +312,11 @@
auto fields = android::base::Split(line.c_str(), ":");
android::base::ParseUint(fields[0], &aggregationKey);
- for (int j = 1; j < fields.size(); j++) {
+ for (size_t j = 1; j < fields.size(); j++) {
auto numbers = android::base::Split(fields[j], " ");
std::vector<uint64_t> chunk;
- for (int k = 0; k < numbers.size(); k++) {
+ for (size_t k = 0; k < numbers.size(); k++) {
uint64_t time;
android::base::ParseUint(numbers[k], &time);
chunk.emplace_back(time);
diff --git a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
index 1f29735..dab47e9 100644
--- a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
+++ b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
@@ -288,7 +288,7 @@
}
bool nonZero = false;
- for (int i = 0; i < vector->size(); i++) {
+ for (size_t i = 0; i < vector->size(); i++) {
jint index = scopedIndexMap[i];
if (index < 0 || index >= size) {
jniThrowExceptionFmt(env, "java/lang/IndexOutOfBoundsException",
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 9c1bea7..7c5885a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1094,8 +1094,8 @@
}
struct dirent* ent;
while ((ent = readdir(dir.get()))) {
- if (ent->d_ino == ce_data_inode) {
- return ent->d_name;
+ if (static_cast<long long>(ent->d_ino) == ce_data_inode) {
+ return ent->d_name;
}
}
}
@@ -1765,14 +1765,14 @@
static void ReloadBuildJavaConstants(JNIEnv* env) {
jclass build_cls = env->FindClass("android/os/Build");
size_t arr_size = sizeof(build_constants) / sizeof(build_constants[0]);
- for (int i = 0; i < arr_size; i++) {
+ for (size_t i = 0; i < arr_size; i++) {
const char* field_name = build_constants[i].first;
const char* sysprop_name = build_constants[i].second;
ReloadBuildJavaConstant(env, build_cls, field_name, "Ljava/lang/String;", sysprop_name);
}
jclass build_version_cls = env->FindClass("android/os/Build$VERSION");
arr_size = sizeof(build_version_constants) / sizeof(build_version_constants[0]);
- for (int i = 0; i < arr_size; i++) {
+ for (size_t i = 0; i < arr_size; i++) {
const char* field_name = build_version_constants[i].first;
const char* sysprop_name = build_version_constants[i].second;
ReloadBuildJavaConstant(env, build_version_cls, field_name, "Ljava/lang/String;", sysprop_name);
@@ -2901,7 +2901,7 @@
return -1;
}
ScopedByteArrayRO source(env, in);
- if (source.size() < length) {
+ if (source.size() < static_cast<size_t>(length)) {
// Invalid parameter
jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
return -1;
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index 2b5b8f7..87ab496 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -76,7 +76,7 @@
return {};
}
fail_fn(CREATE_ERROR("session socket read failed: %s", strerror(errno)));
- } else if (nread == MAX_COMMAND_BYTES - mEnd) {
+ } else if (nread == static_cast<ssize_t>(MAX_COMMAND_BYTES - mEnd)) {
// This is pessimistic by one character, but close enough.
fail_fn("ZygoteCommandBuffer overflowed: command too long");
}
@@ -136,7 +136,7 @@
}
char* countString = line.value().first; // Newline terminated.
long nArgs = atol(countString);
- if (nArgs <= 0 || nArgs >= MAX_COMMAND_BYTES / 2) {
+ if (nArgs <= 0 || nArgs >= static_cast<long>(MAX_COMMAND_BYTES / 2)) {
fail_fn(CREATE_ERROR("Unreasonable argument count %ld", nArgs));
}
mLinesLeft = nArgs;
@@ -153,7 +153,7 @@
// As a side effect, this sets mNiceName to a non-empty string, if possible.
template<class FailFn>
bool isSimpleForkCommand(int minUid, FailFn fail_fn) {
- if (mLinesLeft <= 0 || mLinesLeft >= MAX_COMMAND_BYTES / 2) {
+ if (mLinesLeft <= 0 || mLinesLeft >= static_cast<int32_t>(MAX_COMMAND_BYTES / 2)) {
return false;
}
static const char* RUNTIME_ARGS = "--runtime-args";
@@ -179,14 +179,14 @@
if (!read_result.has_value()) {
return false;
}
- auto [arg_start, arg_end] = read_result.value();
- if (arg_end - arg_start == RA_LENGTH
- && strncmp(arg_start, RUNTIME_ARGS, RA_LENGTH) == 0) {
+ const auto [arg_start, arg_end] = read_result.value();
+ if (static_cast<size_t>(arg_end - arg_start) == RA_LENGTH &&
+ strncmp(arg_start, RUNTIME_ARGS, RA_LENGTH) == 0) {
saw_runtime_args = true;
continue;
}
- if (arg_end - arg_start >= NN_LENGTH
- && strncmp(arg_start, NICE_NAME, NN_LENGTH) == 0) {
+ if (static_cast<size_t>(arg_end - arg_start) >= NN_LENGTH &&
+ strncmp(arg_start, NICE_NAME, NN_LENGTH) == 0) {
size_t name_len = arg_end - (arg_start + NN_LENGTH);
size_t copy_len = std::min(name_len, NICE_NAME_BYTES - 1);
memcpy(mNiceName, arg_start + NN_LENGTH, copy_len);
@@ -196,21 +196,21 @@
}
continue;
}
- if (arg_end - arg_start == IW_LENGTH
- && strncmp(arg_start, INVOKE_WITH, IW_LENGTH) == 0) {
+ if (static_cast<size_t>(arg_end - arg_start) == IW_LENGTH &&
+ strncmp(arg_start, INVOKE_WITH, IW_LENGTH) == 0) {
// This also removes the need for invoke-with security checks here.
return false;
}
- if (arg_end - arg_start == CZ_LENGTH
- && strncmp(arg_start, CHILD_ZYGOTE, CZ_LENGTH) == 0) {
+ if (static_cast<size_t>(arg_end - arg_start) == CZ_LENGTH &&
+ strncmp(arg_start, CHILD_ZYGOTE, CZ_LENGTH) == 0) {
return false;
}
- if (arg_end - arg_start >= CA_LENGTH
- && strncmp(arg_start, CAPABILITIES, CA_LENGTH) == 0) {
+ if (static_cast<size_t>(arg_end - arg_start) >= CA_LENGTH &&
+ strncmp(arg_start, CAPABILITIES, CA_LENGTH) == 0) {
return false;
}
- if (arg_end - arg_start >= SU_LENGTH
- && strncmp(arg_start, SETUID, SU_LENGTH) == 0) {
+ if (static_cast<size_t>(arg_end - arg_start) >= SU_LENGTH &&
+ strncmp(arg_start, SETUID, SU_LENGTH) == 0) {
int uid = digitsVal(arg_start + SU_LENGTH, arg_end);
if (uid < minUid) {
return false;
@@ -218,8 +218,8 @@
saw_setuid = true;
continue;
}
- if (arg_end - arg_start >= SG_LENGTH
- && strncmp(arg_start, SETGID, SG_LENGTH) == 0) {
+ if (static_cast<size_t>(arg_end - arg_start) >= SG_LENGTH &&
+ strncmp(arg_start, SETGID, SG_LENGTH) == 0) {
int gid = digitsVal(arg_start + SG_LENGTH, arg_end);
if (gid == -1) {
return false;
@@ -422,7 +422,7 @@
bool first_time = true;
do {
- if (credentials.uid != expected_uid) {
+ if (credentials.uid != static_cast<uid_t>(expected_uid)) {
return JNI_FALSE;
}
n_buffer->readAllLines(first_time ? fail_fn_1 : fail_fn_n);
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroup.java b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
index 1a9ebbc..d607126 100644
--- a/media/java/android/media/audiopolicy/AudioVolumeGroup.java
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
@@ -17,6 +17,7 @@
package android.media.audiopolicy;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.media.AudioAttributes;
import android.media.AudioSystem;
@@ -107,7 +108,7 @@
}
@Override
- public boolean equals(@NonNull Object o) {
+ public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
index 08a8d89..2769dbc 100644
--- a/media/jni/android_media_MediaMetricsJNI.cpp
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -127,7 +127,7 @@
if (item->getTimestamp() > 0) {
bh.put(mediametrics::BUNDLE_TIMESTAMP, (int64_t)item->getTimestamp());
}
- if (item->getUid() != -1) {
+ if (static_cast<int32_t>(item->getUid()) != -1) {
bh.put(mediametrics::BUNDLE_UID, (int32_t)item->getUid());
}
for (const auto &prop : *item) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index f074106..f03263b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -23,6 +23,7 @@
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.Drawable;
+import android.hardware.usb.flags.Flags;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
@@ -704,12 +705,23 @@
continue;
}
for (int complianceWarningType : complianceWarnings) {
- switch (complianceWarningType) {
- case UsbPortStatus.COMPLIANCE_WARNING_OTHER:
- case UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY:
- return true;
- default:
- break;
+ if (Flags.enableUsbDataComplianceWarning()
+ && Flags.enableInputPowerLimitedWarning()) {
+ switch (complianceWarningType) {
+ case UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED:
+ case UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY:
+ return true;
+ default:
+ break;
+ }
+ } else {
+ switch (complianceWarningType) {
+ case UsbPortStatus.COMPLIANCE_WARNING_OTHER:
+ case UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY:
+ return true;
+ default:
+ break;
+ }
}
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index 29846ac..a88a9c7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -28,6 +28,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.hardware.usb.flags.Flags;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
@@ -36,6 +37,7 @@
import android.os.BatteryManager;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
import android.telephony.NetworkRegistrationInfo;
@@ -44,6 +46,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
@@ -85,6 +88,8 @@
@Mock
private UsbPortStatus mUsbPortStatus;
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -425,8 +430,38 @@
}
@Test
- public void containsIncompatibleChargers_complianeWarningOther_returnTrue() {
+ public void containsIncompatibleChargers_complianeWarningOther_returnTrue_flagDisabled() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING);
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_INPUT_POWER_LIMITED_WARNING);
setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_OTHER);
+
+ assertThat(Utils.containsIncompatibleChargers(mContext, TAG)).isTrue();
+ }
+
+ @Test
+ public void containsIncompatibleChargers_complianeWarningPower_returnFalse_flagDisabled() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING);
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_INPUT_POWER_LIMITED_WARNING);
+ setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED);
+
+ assertThat(Utils.containsIncompatibleChargers(mContext, TAG)).isFalse();
+ }
+
+ @Test
+ public void containsIncompatibleChargers_complianeWarningOther_returnFalse_flagEnabled() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_INPUT_POWER_LIMITED_WARNING);
+ setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_OTHER);
+
+ assertThat(Utils.containsIncompatibleChargers(mContext, TAG)).isFalse();
+ }
+
+ @Test
+ public void containsIncompatibleChargers_complianeWarningPower_returnTrue_flagEnabled() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_INPUT_POWER_LIMITED_WARNING);
+ setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED);
+
assertThat(Utils.containsIncompatibleChargers(mContext, TAG)).isTrue();
}
@@ -446,7 +481,6 @@
public void containsIncompatibleChargers_emptyComplianceWarnings_returnFalse() {
setupIncompatibleCharging();
when(mUsbPortStatus.getComplianceWarnings()).thenReturn(new int[1]);
-
assertThat(Utils.containsIncompatibleChargers(mContext, TAG)).isFalse();
}
@@ -476,7 +510,7 @@
}
private void setupIncompatibleCharging() {
- setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_OTHER);
+ setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY);
}
private void setupIncompatibleCharging(int complianceWarningType) {
diff --git a/packages/SystemUI/src/com/android/systemui/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/complication/SmartSpaceComplication.java
index b98794e..9bb23d8 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/SmartSpaceComplication.java
@@ -71,6 +71,18 @@
private final DreamOverlayStateController mDreamOverlayStateController;
private final SmartSpaceComplication mComplication;
private final FeatureFlags mFeatureFlags;
+ private final DreamOverlayStateController.Callback mStateControllerCallback =
+ new DreamOverlayStateController.Callback() {
+ @Override
+ public void onStateChanged() {
+ if (mDreamOverlayStateController.isOverlayActive()) {
+ mSmartSpaceController.addListener(mSmartspaceListener);
+ } else {
+ mSmartSpaceController.removeListener(mSmartspaceListener);
+ mDreamOverlayStateController.removeComplication(mComplication);
+ }
+ }
+ };
private final BcSmartspaceDataPlugin.SmartspaceTargetListener mSmartspaceListener =
new BcSmartspaceDataPlugin.SmartspaceTargetListener() {
@@ -103,17 +115,7 @@
return;
}
- mDreamOverlayStateController.addCallback(new DreamOverlayStateController.Callback() {
- @Override
- public void onStateChanged() {
- if (mDreamOverlayStateController.isOverlayActive()) {
- mSmartSpaceController.addListener(mSmartspaceListener);
- } else {
- mSmartSpaceController.removeListener(mSmartspaceListener);
- mDreamOverlayStateController.removeComplication(mComplication);
- }
- }
- });
+ mDreamOverlayStateController.addCallback(mStateControllerCallback);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 8eb80ad..b34b459 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -130,6 +130,7 @@
import com.android.systemui.util.concurrency.SysUIConcurrencyModule;
import com.android.systemui.util.dagger.UtilModule;
import com.android.systemui.util.kotlin.CoroutinesModule;
+import com.android.systemui.util.reference.ReferenceModule;
import com.android.systemui.util.sensors.SensorModule;
import com.android.systemui.util.settings.SettingsUtilModule;
import com.android.systemui.util.time.SystemClock;
@@ -201,6 +202,7 @@
PrivacyModule.class,
QRCodeScannerModule.class,
QSFragmentStartableModule.class,
+ ReferenceModule.class,
RetailModeModule.class,
ScreenshotModule.class,
SensorModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
index c9748f9..0e333f2 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
@@ -31,11 +31,15 @@
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.dagger.DreamLog;
import com.android.systemui.statusbar.policy.CallbackController;
+import com.android.systemui.util.annotations.WeaklyReferencedCallback;
+import com.android.systemui.util.reference.WeakReferenceFactory;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -68,7 +72,10 @@
/**
* Callback for dream overlay events.
+ * NOTE: Caller should maintain a strong reference to this themselves so the callback does
+ * not get garbage collected.
*/
+ @WeaklyReferencedCallback
public interface Callback {
/**
* Called when the composition of complications changes.
@@ -97,7 +104,7 @@
private final Executor mExecutor;
private final boolean mOverlayEnabled;
- private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+ private final ArrayList<WeakReference<Callback>> mCallbacks = new ArrayList<>();
@Complication.ComplicationType
private int mAvailableComplicationTypes = Complication.COMPLICATION_TYPE_NONE;
@@ -107,6 +114,7 @@
private final Collection<Complication> mComplications = new HashSet();
private final FeatureFlags mFeatureFlags;
+ private final WeakReferenceFactory mWeakReferenceFactory;
private final int mSupportedTypes;
@@ -117,11 +125,13 @@
public DreamOverlayStateController(@Main Executor executor,
@Named(DREAM_OVERLAY_ENABLED) boolean overlayEnabled,
FeatureFlags featureFlags,
- @DreamLog LogBuffer logBuffer) {
+ @DreamLog LogBuffer logBuffer,
+ WeakReferenceFactory weakReferenceFactory) {
mExecutor = executor;
mOverlayEnabled = overlayEnabled;
mLogger = new DreamLogger(logBuffer, TAG);
mFeatureFlags = featureFlags;
+ mWeakReferenceFactory = weakReferenceFactory;
if (mFeatureFlags.isEnabled(Flags.ALWAYS_SHOW_HOME_CONTROLS_ON_DREAMS)) {
mSupportedTypes = Complication.COMPLICATION_TYPE_NONE
| Complication.COMPLICATION_TYPE_HOME_CONTROLS;
@@ -143,7 +153,7 @@
mExecutor.execute(() -> {
if (mComplications.add(complication)) {
mLogger.logAddComplication(complication.toString());
- mCallbacks.stream().forEach(callback -> callback.onComplicationsChanged());
+ notifyCallbacksLocked(Callback::onComplicationsChanged);
}
});
}
@@ -160,7 +170,7 @@
mExecutor.execute(() -> {
if (mComplications.remove(complication)) {
mLogger.logRemoveComplication(complication.toString());
- mCallbacks.stream().forEach(callback -> callback.onComplicationsChanged());
+ notifyCallbacksLocked(Callback::onComplicationsChanged);
}
});
}
@@ -199,22 +209,33 @@
}
private void notifyCallbacks(Consumer<Callback> callbackConsumer) {
- mExecutor.execute(() -> {
- for (Callback callback : mCallbacks) {
+ mExecutor.execute(() -> notifyCallbacksLocked(callbackConsumer));
+ }
+
+ private void notifyCallbacksLocked(Consumer<Callback> callbackConsumer) {
+ final Iterator<WeakReference<Callback>> iterator = mCallbacks.iterator();
+ while (iterator.hasNext()) {
+ final Callback callback = iterator.next().get();
+ // Remove any callbacks which have been GC'd
+ if (callback == null) {
+ iterator.remove();
+ } else {
callbackConsumer.accept(callback);
}
- });
+ }
}
@Override
public void addCallback(@NonNull Callback callback) {
mExecutor.execute(() -> {
Objects.requireNonNull(callback, "Callback must not be null. b/128895449");
- if (mCallbacks.contains(callback)) {
+ final boolean containsCallback = mCallbacks.stream()
+ .anyMatch(reference -> reference.get() == callback);
+ if (containsCallback) {
return;
}
- mCallbacks.add(callback);
+ mCallbacks.add(mWeakReferenceFactory.create(callback));
if (mComplications.isEmpty()) {
return;
@@ -228,7 +249,13 @@
public void removeCallback(@NonNull Callback callback) {
mExecutor.execute(() -> {
Objects.requireNonNull(callback, "Callback must not be null. b/128895449");
- mCallbacks.remove(callback);
+ final Iterator<WeakReference<Callback>> iterator = mCallbacks.iterator();
+ while (iterator.hasNext()) {
+ final Callback cb = iterator.next().get();
+ if (cb == null || cb == callback) {
+ iterator.remove();
+ }
+ }
});
}
@@ -318,7 +345,7 @@
if (isLowLightActive() && !active) {
// Notify that we're exiting low light only on the transition from active to not active.
- mCallbacks.forEach(Callback::onExitLowLight);
+ notifyCallbacks(Callback::onExitLowLight);
}
modifyState(active ? OP_SET_STATE : OP_CLEAR_STATE, STATE_LOW_LIGHT_ACTIVE);
}
@@ -375,7 +402,7 @@
mExecutor.execute(() -> {
mLogger.logAvailableComplicationTypes(types);
mAvailableComplicationTypes = types;
- mCallbacks.forEach(Callback::onAvailableComplicationTypesChanged);
+ notifyCallbacksLocked(Callback::onAvailableComplicationTypesChanged);
});
}
@@ -393,7 +420,7 @@
mExecutor.execute(() -> {
mLogger.logShouldShowComplications(shouldShowComplications);
mShouldShowComplications = shouldShowComplications;
- mCallbacks.forEach(Callback::onAvailableComplicationTypesChanged);
+ notifyCallbacksLocked(Callback::onAvailableComplicationTypesChanged);
});
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
index 654f2d1..f5f5571 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
@@ -66,7 +66,7 @@
/**
* Acts as source of truth for biometric authentication related settings like enrollments, device
- * policy, etc.
+ * policy specifically for device entry usage.
*
* Abstracts-away data sources and their schemas so the rest of the app doesn't need to worry about
* upstream changes.
@@ -74,7 +74,8 @@
interface BiometricSettingsRepository {
/**
* If the current user can enter the device using fingerprint. This is true if user has enrolled
- * fingerprints and fingerprint auth is not disabled through settings/device policy
+ * fingerprints and fingerprint auth is not disabled for device entry through settings and
+ * device policy
*/
val isFingerprintEnrolledAndEnabled: StateFlow<Boolean>
@@ -247,9 +248,11 @@
}
}
- private val isFaceEnabledByBiometricsManagerForCurrentUser: Flow<Boolean> =
+ private val areBiometricsEnabledForCurrentUser: Flow<Boolean> =
userRepository.selectedUserInfo.flatMapLatest { userInfo ->
- isFaceEnabledByBiometricsManager.map { biometricsEnabledForUser[userInfo.id] ?: false }
+ areBiometricsEnabledForDeviceEntryFromUserSetting.map {
+ biometricsEnabledForUser[userInfo.id] ?: false
+ }
}
private val isFaceEnabledByDevicePolicy: Flow<Boolean> =
@@ -263,13 +266,13 @@
.distinctUntilChanged()
private val isFaceAuthenticationEnabled: Flow<Boolean> =
- combine(isFaceEnabledByBiometricsManagerForCurrentUser, isFaceEnabledByDevicePolicy) {
+ combine(areBiometricsEnabledForCurrentUser, isFaceEnabledByDevicePolicy) {
biometricsManagerSetting,
devicePolicySetting ->
biometricsManagerSetting && devicePolicySetting
}
- private val isFaceEnabledByBiometricsManager: Flow<Pair<Int, Boolean>> =
+ private val areBiometricsEnabledForDeviceEntryFromUserSetting: Flow<Pair<Int, Boolean>> =
conflatedCallbackFlow {
val callback =
object : IBiometricEnabledOnKeyguardCallback.Stub() {
@@ -340,6 +343,7 @@
override val isFingerprintEnrolledAndEnabled: StateFlow<Boolean> =
isFingerprintEnrolled
+ .and(areBiometricsEnabledForCurrentUser)
.and(isFingerprintEnabledByDevicePolicy)
.stateIn(scope, SharingStarted.Eagerly, false)
diff --git a/packages/SystemUI/src/com/android/systemui/util/reference/ReferenceModule.kt b/packages/SystemUI/src/com/android/systemui/util/reference/ReferenceModule.kt
new file mode 100644
index 0000000..e7a91e5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/reference/ReferenceModule.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.reference
+
+import dagger.Binds
+import dagger.Module
+
+@Module
+abstract class ReferenceModule {
+ @Binds
+ abstract fun bindWeakReferenceFactory(impl: WeakReferenceFactoryImpl): WeakReferenceFactory
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/reference/WeakReferenceFactory.kt b/packages/SystemUI/src/com/android/systemui/util/reference/WeakReferenceFactory.kt
new file mode 100644
index 0000000..658f040
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/reference/WeakReferenceFactory.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.reference
+
+import java.lang.ref.WeakReference
+import javax.inject.Inject
+
+interface WeakReferenceFactory {
+ fun <T> create(referent: T): WeakReference<T>
+}
+
+class WeakReferenceFactoryImpl @Inject constructor() : WeakReferenceFactory {
+ override fun <T> create(referent: T): WeakReference<T> {
+ return WeakReference(referent)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationCollectionLiveDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationCollectionLiveDataTest.java
index 40f0ed3..288f3b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationCollectionLiveDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationCollectionLiveDataTest.java
@@ -33,6 +33,7 @@
import com.android.systemui.flags.Flags;
import com.android.systemui.log.core.FakeLogBuffer;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.reference.FakeWeakReferenceFactory;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
@@ -68,7 +69,8 @@
mExecutor,
/* overlayEnabled= */ true,
mFeatureFlags,
- FakeLogBuffer.Factory.Companion.create());
+ FakeLogBuffer.Factory.Companion.create(),
+ new FakeWeakReferenceFactory());
mLiveData = new ComplicationCollectionLiveData(mStateController);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
index 365f67b..6d5cd49 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
@@ -36,6 +36,7 @@
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.core.FakeLogBuffer;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.reference.FakeWeakReferenceFactory;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
@@ -63,6 +64,8 @@
final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+ final FakeWeakReferenceFactory mWeakReferenceFactory = new FakeWeakReferenceFactory();
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -407,12 +410,36 @@
assertThat(stateController.getComplications()).contains(homeControlsComplication);
}
+ @Test
+ public void testCallbacksIgnoredWhenWeakReferenceCleared() {
+ final DreamOverlayStateController.Callback callback1 = Mockito.mock(
+ DreamOverlayStateController.Callback.class);
+ final DreamOverlayStateController.Callback callback2 = Mockito.mock(
+ DreamOverlayStateController.Callback.class);
+
+ final DreamOverlayStateController stateController = getDreamOverlayStateController(true);
+ stateController.addCallback(callback1);
+ stateController.addCallback(callback2);
+ mExecutor.runAllReady();
+
+ // Simulate callback1 getting GC'd by clearing the reference
+ mWeakReferenceFactory.clear(callback1);
+ stateController.setOverlayActive(true);
+ mExecutor.runAllReady();
+
+ // Callback2 should still be called, but never callback1
+ verify(callback1, never()).onStateChanged();
+ verify(callback2).onStateChanged();
+ assertThat(stateController.isOverlayActive()).isTrue();
+ }
+
private DreamOverlayStateController getDreamOverlayStateController(boolean overlayEnabled) {
return new DreamOverlayStateController(
mExecutor,
overlayEnabled,
mFeatureFlags,
- mLogBuffer
+ mLogBuffer,
+ mWeakReferenceFactory
);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
index 90fd652..4587ea6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -154,6 +154,7 @@
fun fingerprintEnrollmentChange() =
testScope.runTest {
createBiometricSettingsRepository()
+ biometricsAreEnabledBySettings()
val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled)
runCurrent()
@@ -170,11 +171,34 @@
}
@Test
+ fun fingerprintEnabledStateChange() =
+ testScope.runTest {
+ createBiometricSettingsRepository()
+ biometricsAreEnabledBySettings()
+ val fingerprintAllowed = collectLastValue(underTest.isFingerprintEnrolledAndEnabled)
+ runCurrent()
+
+ // start state
+ whenever(authController.isFingerprintEnrolled(anyInt())).thenReturn(true)
+ enrollmentChange(UNDER_DISPLAY_FINGERPRINT, PRIMARY_USER_ID, true)
+ assertThat(fingerprintAllowed()).isTrue()
+
+ // when biometrics are not enabled by settings
+ biometricsAreNotEnabledBySettings()
+ assertThat(fingerprintAllowed()).isFalse()
+
+ // when biometrics are enabled by settings
+ biometricsAreEnabledBySettings()
+ assertThat(fingerprintAllowed()).isTrue()
+ }
+
+ @Test
fun strongBiometricAllowedChange() =
testScope.runTest {
fingerprintIsEnrolled()
doNotDisableKeyguardAuthFeatures()
createBiometricSettingsRepository()
+ biometricsAreEnabledBySettings()
val strongBiometricAllowed by
collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
@@ -197,7 +221,7 @@
createBiometricSettingsRepository()
val convenienceFaceAuthAllowed by collectLastValue(underTest.isFaceAuthCurrentlyAllowed)
doNotDisableKeyguardAuthFeatures()
- faceAuthIsEnabledByBiometricManager()
+ biometricsAreEnabledBySettings()
onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
onNonStrongAuthChanged(true, PRIMARY_USER_ID)
@@ -238,6 +262,7 @@
faceAuthIsNonStrongBiometric()
faceAuthIsEnrolled()
doNotDisableKeyguardAuthFeatures()
+ biometricsAreEnabledBySettings()
val convenienceBiometricAllowed = collectLastValue(underTest.isFaceAuthCurrentlyAllowed)
runCurrent()
@@ -258,7 +283,7 @@
faceAuthIsEnrolled()
createBiometricSettingsRepository()
doNotDisableKeyguardAuthFeatures()
- faceAuthIsEnabledByBiometricManager()
+ biometricsAreEnabledBySettings()
runCurrent()
val convenienceBiometricAllowed by
@@ -291,6 +316,7 @@
testScope.runTest {
fingerprintIsEnrolled(PRIMARY_USER_ID)
createBiometricSettingsRepository()
+ biometricsAreEnabledBySettings()
val fingerprintEnabledByDevicePolicy =
collectLastValue(underTest.isFingerprintEnrolledAndEnabled)
@@ -316,7 +342,7 @@
createBiometricSettingsRepository()
val faceAuthAllowed = collectLastValue(underTest.isFaceAuthEnrolledAndEnabled)
- faceAuthIsEnabledByBiometricManager()
+ biometricsAreEnabledBySettings()
doNotDisableKeyguardAuthFeatures(PRIMARY_USER_ID)
@@ -351,12 +377,18 @@
assertThat(faceAuthAllowed()).isTrue()
}
- private fun faceAuthIsEnabledByBiometricManager(userId: Int = PRIMARY_USER_ID) {
+ private fun biometricsAreEnabledBySettings(userId: Int = PRIMARY_USER_ID) {
verify(biometricManager, atLeastOnce())
.registerEnabledOnKeyguardCallback(biometricManagerCallback.capture())
biometricManagerCallback.value.onChanged(true, userId)
}
+ private fun biometricsAreNotEnabledBySettings(userId: Int = PRIMARY_USER_ID) {
+ verify(biometricManager, atLeastOnce())
+ .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture())
+ biometricManagerCallback.value.onChanged(false, userId)
+ }
+
@Test
fun faceEnrollmentStatusOfNewUserUponUserSwitch() =
testScope.runTest {
@@ -427,7 +459,7 @@
faceAuthIsEnrolled()
createBiometricSettingsRepository()
- faceAuthIsEnabledByBiometricManager()
+ biometricsAreEnabledBySettings()
doNotDisableKeyguardAuthFeatures()
mobileConnectionsRepository.isAnySimSecure.value = false
runCurrent()
@@ -454,7 +486,7 @@
deviceIsInPostureThatSupportsFaceAuth()
doNotDisableKeyguardAuthFeatures()
faceAuthIsStrongBiometric()
- faceAuthIsEnabledByBiometricManager()
+ biometricsAreEnabledBySettings()
mobileConnectionsRepository.isAnySimSecure.value = false
onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
@@ -636,7 +668,7 @@
deviceIsInPostureThatSupportsFaceAuth()
doNotDisableKeyguardAuthFeatures()
faceAuthIsStrongBiometric()
- faceAuthIsEnabledByBiometricManager()
+ biometricsAreEnabledBySettings()
onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
onNonStrongAuthChanged(false, PRIMARY_USER_ID)
@@ -660,7 +692,7 @@
deviceIsInPostureThatSupportsFaceAuth()
doNotDisableKeyguardAuthFeatures()
faceAuthIsNonStrongBiometric()
- faceAuthIsEnabledByBiometricManager()
+ biometricsAreEnabledBySettings()
onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
onNonStrongAuthChanged(false, PRIMARY_USER_ID)
@@ -682,6 +714,7 @@
fun fpAuthCurrentlyAllowed_dependsOnNonStrongAuthBiometricSetting_ifFpIsNotStrong() =
testScope.runTest {
createBiometricSettingsRepository()
+ biometricsAreEnabledBySettings()
val isFingerprintCurrentlyAllowed by
collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
@@ -723,6 +756,7 @@
fun fpAuthCurrentlyAllowed_dependsOnStrongAuthBiometricSetting_ifFpIsStrong() =
testScope.runTest {
createBiometricSettingsRepository()
+ biometricsAreEnabledBySettings()
val isFingerprintCurrentlyAllowed by
collectLastValue(underTest.isFingerprintAuthCurrentlyAllowed)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
index 58d93c9..2f79955 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
@@ -294,6 +294,6 @@
when(mUsbPort.supportsComplianceWarnings()).thenReturn(true);
when(mUsbPortStatus.isConnected()).thenReturn(true);
when(mUsbPortStatus.getComplianceWarnings())
- .thenReturn(new int[]{UsbPortStatus.COMPLIANCE_WARNING_OTHER});
+ .thenReturn(new int[]{UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY});
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/reference/FakeWeakReferenceFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/reference/FakeWeakReferenceFactory.kt
new file mode 100644
index 0000000..f0a8fd0
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/reference/FakeWeakReferenceFactory.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.reference
+
+import java.lang.ref.WeakReference
+
+class FakeWeakReferenceFactory : WeakReferenceFactory {
+ private val managedReferents = mutableListOf<WeakReference<*>>()
+
+ override fun <T> create(referent: T): WeakReference<T> {
+ val weakRef = WeakReference(referent)
+ managedReferents.add(weakRef)
+ return weakRef
+ }
+
+ /**
+ * Clears any [WeakReference] objects pointing to this object. If argument is null, clears all
+ * references.
+ */
+ fun <T> clear(referent: T) {
+ managedReferents.filter { it.get() == referent }.forEach { it.clear() }
+ }
+}
diff --git a/services/autofill/bugfixes.aconfig b/services/autofill/bugfixes.aconfig
index b37bbd6..ab678d9 100644
--- a/services/autofill/bugfixes.aconfig
+++ b/services/autofill/bugfixes.aconfig
@@ -20,3 +20,10 @@
description: "Mitigation for relayout issue"
bug: "294330426"
}
+
+flag {
+ name: "ignore_view_state_reset_to_empty"
+ namespace: "autofill"
+ description: "Mitigation for view state reset to empty causing no save dialog to show issue"
+ bug: "297976948"
+}
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index afc0dd1..cd9c53b 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -83,6 +83,9 @@
}
],
"file_patterns": ["VpnManagerService\\.java"]
+ },
+ {
+ "name": "FrameworksNetTests"
}
],
"presubmit-large": [
@@ -124,9 +127,6 @@
},
{
"name": "CtsSuspendAppsTestCases"
- },
- {
- "name": "FrameworksNetTests"
}
]
}
diff --git a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
index b006ac8..a8cba53 100644
--- a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
@@ -35,11 +35,12 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
-import com.android.server.pm.UserManagerInternal;
import com.android.server.LocalServices;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
+import com.android.server.pm.UserManagerInternal;
import libcore.io.IoUtils;
@@ -53,6 +54,9 @@
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
@@ -114,21 +118,26 @@
private static final String GSI_RUNNING_PROP = "ro.gsid.image_running";
private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
- private static final int HEADER_SIZE = 8;
+ @VisibleForTesting
+ static final int HEADER_SIZE = 8;
// Magic number to mark block device as adhering to the format consumed by this service
private static final int PARTITION_TYPE_MARKER = 0x19901873;
/** Size of the block reserved for FRP credential, including 4 bytes for the size header. */
private static final int FRP_CREDENTIAL_RESERVED_SIZE = 1000;
/** Maximum size of the FRP credential handle that can be stored. */
- private static final int MAX_FRP_CREDENTIAL_HANDLE_SIZE = FRP_CREDENTIAL_RESERVED_SIZE - 4;
+ @VisibleForTesting
+ static final int MAX_FRP_CREDENTIAL_HANDLE_SIZE = FRP_CREDENTIAL_RESERVED_SIZE - 4;
/**
* Size of the block reserved for Test Harness Mode data, including 4 bytes for the size header.
*/
private static final int TEST_MODE_RESERVED_SIZE = 10000;
/** Maximum size of the Test Harness Mode data that can be stored. */
- private static final int MAX_TEST_MODE_DATA_SIZE = TEST_MODE_RESERVED_SIZE - 4;
+ @VisibleForTesting
+ static final int MAX_TEST_MODE_DATA_SIZE = TEST_MODE_RESERVED_SIZE - 4;
+
// Limit to 100k as blocks larger than this might cause strain on Binder.
- private static final int MAX_DATA_BLOCK_SIZE = 1024 * 100;
+ @VisibleForTesting
+ static final int MAX_DATA_BLOCK_SIZE = 1024 * 100;
public static final int DIGEST_SIZE_BYTES = 32;
private static final String OEM_UNLOCK_PROP = "sys.oem_unlock_allowed";
@@ -138,12 +147,12 @@
private final Context mContext;
private final String mDataBlockFile;
- private final boolean mIsRunningDSU;
+ private final boolean mIsFileBacked;
private final Object mLock = new Object();
private final CountDownLatch mInitDoneSignal = new CountDownLatch(1);
private int mAllowedUid = -1;
- private long mBlockDeviceSize;
+ private long mBlockDeviceSize = -1; // Load lazily
@GuardedBy("mLock")
private boolean mIsWritable = true;
@@ -151,13 +160,23 @@
public PersistentDataBlockService(Context context) {
super(context);
mContext = context;
- mIsRunningDSU = SystemProperties.getBoolean(GSI_RUNNING_PROP, false);
- if (mIsRunningDSU) {
+ if (SystemProperties.getBoolean(GSI_RUNNING_PROP, false)) {
+ mIsFileBacked = true;
mDataBlockFile = GSI_SANDBOX;
} else {
+ mIsFileBacked = false;
mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
}
- mBlockDeviceSize = -1; // Load lazily
+ }
+
+ @VisibleForTesting
+ PersistentDataBlockService(Context context, boolean isFileBacked, String dataBlockFile,
+ long blockDeviceSize) {
+ super(context);
+ mContext = context;
+ mIsFileBacked = isFileBacked;
+ mDataBlockFile = dataBlockFile;
+ mBlockDeviceSize = blockDeviceSize;
}
private int getAllowedUid() {
@@ -212,6 +231,11 @@
super.onBootPhase(phase);
}
+ @VisibleForTesting
+ void setAllowedUid(int uid) {
+ mAllowedUid = uid;
+ }
+
private void formatIfOemUnlockEnabled() {
boolean enabled = doGetOemUnlockEnabled();
if (enabled) {
@@ -220,7 +244,7 @@
}
}
- SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
+ setProperty(OEM_UNLOCK_PROP, enabled ? "1" : "0");
}
private void enforceOemUnlockReadPermission() {
@@ -278,7 +302,7 @@
private long getBlockDeviceSize() {
synchronized (mLock) {
if (mBlockDeviceSize == -1) {
- if (mIsRunningDSU) {
+ if (mIsFileBacked) {
mBlockDeviceSize = MAX_DATA_BLOCK_SIZE;
} else {
mBlockDeviceSize = nativeGetBlockDeviceSize(mDataBlockFile);
@@ -289,14 +313,26 @@
return mBlockDeviceSize;
}
- private long getFrpCredentialDataOffset() {
- return getBlockDeviceSize() - 1 - FRP_CREDENTIAL_RESERVED_SIZE;
+ @VisibleForTesting
+ int getMaximumFrpDataSize() {
+ return (int) (getTestHarnessModeDataOffset() - DIGEST_SIZE_BYTES - HEADER_SIZE);
}
- private long getTestHarnessModeDataOffset() {
+ @VisibleForTesting
+ long getFrpCredentialDataOffset() {
+ return getOemUnlockDataOffset() - FRP_CREDENTIAL_RESERVED_SIZE;
+ }
+
+ @VisibleForTesting
+ long getTestHarnessModeDataOffset() {
return getFrpCredentialDataOffset() - TEST_MODE_RESERVED_SIZE;
}
+ @VisibleForTesting
+ long getOemUnlockDataOffset() {
+ return getBlockDeviceSize() - 1;
+ }
+
private boolean enforceChecksumValidity() {
byte[] storedDigest = new byte[DIGEST_SIZE_BYTES];
@@ -385,7 +421,8 @@
return md.digest();
}
- private void formatPartitionLocked(boolean setOemUnlockEnabled) {
+ @VisibleForTesting
+ void formatPartitionLocked(boolean setOemUnlockEnabled) {
try {
FileChannel channel = getBlockOutputChannel();
@@ -448,10 +485,15 @@
Slog.e(TAG, "unable to access persistent partition", e);
return;
} finally {
- SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
+ setProperty(OEM_UNLOCK_PROP, enabled ? "1" : "0");
}
}
+ @VisibleForTesting
+ void setProperty(String name, String value) {
+ SystemProperties.set(name, value);
+ }
+
private boolean doGetOemUnlockEnabled() {
DataInputStream inputStream;
try {
@@ -483,6 +525,16 @@
private native long nativeGetBlockDeviceSize(String path);
private native int nativeWipe(String path);
+ @VisibleForTesting
+ IPersistentDataBlockService getInterfaceForTesting() {
+ return IPersistentDataBlockService.Stub.asInterface(mService);
+ }
+
+ @VisibleForTesting
+ PersistentDataBlockManagerInternal getInternalInterfaceForTesting() {
+ return mInternalService;
+ }
+
private final IBinder mService = new IPersistentDataBlockService.Stub() {
/**
@@ -588,7 +640,18 @@
enforceOemUnlockWritePermission();
synchronized (mLock) {
- int ret = nativeWipe(mDataBlockFile);
+ int ret;
+ if (mIsFileBacked) {
+ try {
+ Files.write(Paths.get(mDataBlockFile), new byte[MAX_DATA_BLOCK_SIZE],
+ StandardOpenOption.TRUNCATE_EXISTING);
+ ret = 0;
+ } catch (IOException e) {
+ ret = -1;
+ }
+ } else {
+ ret = nativeWipe(mDataBlockFile);
+ }
if (ret < 0) {
Slog.e(TAG, "failed to wipe persistent partition");
@@ -699,7 +762,7 @@
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
pw.println("mDataBlockFile: " + mDataBlockFile);
- pw.println("mIsRunningDSU: " + mIsRunningDSU);
+ pw.println("mIsFileBacked: " + mIsFileBacked);
pw.println("mInitDoneSignal: " + mInitDoneSignal);
pw.println("mAllowedUid: " + mAllowedUid);
pw.println("mBlockDeviceSize: " + mBlockDeviceSize);
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 26e70c0..21284a0 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -410,7 +410,7 @@
* Map of all apex system services to the jar files they are contained in.
*/
@GuardedBy("mLock")
- private List<ApexSystemServiceInfo> mApexSystemServices = new ArrayList<>();
+ private final List<ApexSystemServiceInfo> mApexSystemServices = new ArrayList<>();
/**
* Contains the list of {@code packageName}s of apks-in-apex for given
@@ -418,14 +418,14 @@
* difference between {@code packageName} and {@code apexModuleName}.
*/
@GuardedBy("mLock")
- private ArrayMap<String, List<String>> mApksInApex = new ArrayMap<>();
+ private final ArrayMap<String, List<String>> mApksInApex = new ArrayMap<>();
/**
* Contains the list of {@code Exception}s that were raised when installing apk-in-apex
* inside {@code apexModuleName}.
*/
@GuardedBy("mLock")
- private Map<String, String> mErrorWithApkInApex = new ArrayMap<>();
+ private final Map<String, String> mErrorWithApkInApex = new ArrayMap<>();
/**
* An APEX is a file format that delivers the apex-payload wrapped in an apk container. The
diff --git a/services/core/java/com/android/server/pm/AppsFilterBase.java b/services/core/java/com/android/server/pm/AppsFilterBase.java
index 5b32a94..a5bc2c3 100644
--- a/services/core/java/com/android/server/pm/AppsFilterBase.java
+++ b/services/core/java/com/android/server/pm/AppsFilterBase.java
@@ -201,7 +201,7 @@
protected static final boolean CACHE_VALID = true;
protected static final boolean CACHE_INVALID = false;
- protected AtomicBoolean mCacheValid = new AtomicBoolean(CACHE_INVALID);
+ protected final AtomicBoolean mCacheValid = new AtomicBoolean(CACHE_INVALID);
protected boolean isForceQueryable(int callingAppId) {
return mForceQueryable.contains(callingAppId);
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 9bca9f0..36677df 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -89,7 +89,7 @@
private static final long CANCELLATION_WAIT_CHECK_INTERVAL_MS = 200;
- private static ComponentName sDexoptServiceName =
+ private static final ComponentName sDexoptServiceName =
new ComponentName("android", BackgroundDexOptJobService.class.getName());
// Possible return codes of individual optimization steps.
@@ -179,7 +179,7 @@
private final long mDowngradeUnusedAppsThresholdInMillis;
- private List<PackagesUpdatedListener> mPackagesUpdatedListeners = new ArrayList<>();
+ private final List<PackagesUpdatedListener> mPackagesUpdatedListeners = new ArrayList<>();
private int mThermalStatusCutoff = THERMAL_CUTOFF_DEFAULT;
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsService.java b/services/core/java/com/android/server/pm/CrossProfileAppsService.java
index 486282a..0bd165e 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsService.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsService.java
@@ -21,7 +21,7 @@
import com.android.server.SystemService;
public class CrossProfileAppsService extends SystemService {
- private CrossProfileAppsServiceImpl mServiceImpl;
+ private final CrossProfileAppsServiceImpl mServiceImpl;
public CrossProfileAppsService(Context context) {
super(context);
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 5f28e56..f1dc284 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -78,8 +78,8 @@
private final LocalService mLocalService = new LocalService();
- private Context mContext;
- private Injector mInjector;
+ private final Context mContext;
+ private final Injector mInjector;
public CrossProfileAppsServiceImpl(Context context) {
this(context, new InjectorImpl(context));
@@ -783,7 +783,7 @@
}
private static class InjectorImpl implements Injector {
- private Context mContext;
+ private final Context mContext;
public InjectorImpl(Context context) {
mContext = context;
diff --git a/services/core/java/com/android/server/pm/CrossProfileDomainInfo.java b/services/core/java/com/android/server/pm/CrossProfileDomainInfo.java
index 72f3afc..3313e72 100644
--- a/services/core/java/com/android/server/pm/CrossProfileDomainInfo.java
+++ b/services/core/java/com/android/server/pm/CrossProfileDomainInfo.java
@@ -22,10 +22,10 @@
public final class CrossProfileDomainInfo {
/* ResolveInfo for IntentForwarderActivity to send the intent to the other profile */
- ResolveInfo mResolveInfo;
+ final ResolveInfo mResolveInfo;
int mHighestApprovalLevel;
@UserIdInt
- int mTargetUserId = UserHandle.USER_CURRENT; // default as current user
+ final int mTargetUserId;
CrossProfileDomainInfo(ResolveInfo resolveInfo, int highestApprovalLevel, @UserIdInt
int targetUserId) {
@@ -37,6 +37,7 @@
CrossProfileDomainInfo(ResolveInfo resolveInfo, int highestApprovalLevel) {
this.mResolveInfo = resolveInfo;
this.mHighestApprovalLevel = highestApprovalLevel;
+ this.mTargetUserId = UserHandle.USER_CURRENT; // default as current user
}
@Override
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentFilterHelper.java b/services/core/java/com/android/server/pm/CrossProfileIntentFilterHelper.java
index 51214fa..56e9c0a 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentFilterHelper.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentFilterHelper.java
@@ -25,11 +25,11 @@
* Helper class to manage {@link com.android.server.pm.CrossProfileIntentFilter}s.
*/
public class CrossProfileIntentFilterHelper {
- private Context mContext;
- private UserManagerInternal mUserManagerInternal;
- private Settings mSettings;
- private UserManagerService mUserManagerService;
- private PackageManagerTracedLock mLock;
+ private final Context mContext;
+ private final UserManagerInternal mUserManagerInternal;
+ private final Settings mSettings;
+ private final UserManagerService mUserManagerService;
+ private final PackageManagerTracedLock mLock;
public CrossProfileIntentFilterHelper(Settings settings, UserManagerService userManagerService,
PackageManagerTracedLock lock, UserManagerInternal userManagerInternal,
diff --git a/services/core/java/com/android/server/pm/CrossProfileResolver.java b/services/core/java/com/android/server/pm/CrossProfileResolver.java
index a8da818..1d38bbb 100644
--- a/services/core/java/com/android/server/pm/CrossProfileResolver.java
+++ b/services/core/java/com/android/server/pm/CrossProfileResolver.java
@@ -36,8 +36,8 @@
*/
public abstract class CrossProfileResolver {
- protected ComponentResolverApi mComponentResolver;
- protected UserManagerService mUserManager;
+ protected final ComponentResolverApi mComponentResolver;
+ protected final UserManagerService mUserManager;
public CrossProfileResolver(ComponentResolverApi componentResolver,
UserManagerService userManager) {
diff --git a/services/core/java/com/android/server/pm/DataLoaderManagerService.java b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
index 29322e2..888e1c2 100644
--- a/services/core/java/com/android/server/pm/DataLoaderManagerService.java
+++ b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
@@ -50,7 +50,8 @@
private final HandlerThread mThread;
private final Handler mHandler;
private final DataLoaderManagerBinderService mBinderService;
- private SparseArray<DataLoaderServiceConnection> mServiceConnections = new SparseArray<>();
+ private final SparseArray<DataLoaderServiceConnection> mServiceConnections =
+ new SparseArray<>();
public DataLoaderManagerService(Context context) {
super(context);
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFilter.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFilter.java
index dc5915d..db05dd3 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFilter.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFilter.java
@@ -75,10 +75,10 @@
}
static final class Builder {
- private WatchedIntentFilter mFilter = new WatchedIntentFilter();
- private int mFlags;
- private @Direction int mDirection;
- private boolean mLetsPersonalDataIntoProfile;
+ private final WatchedIntentFilter mFilter = new WatchedIntentFilter();
+ private final int mFlags;
+ private final @Direction int mDirection;
+ private final boolean mLetsPersonalDataIntoProfile;
Builder(@Direction int direction, int flags, boolean letsPersonalDataIntoProfile) {
mDirection = direction;
diff --git a/services/core/java/com/android/server/pm/InstallArgs.java b/services/core/java/com/android/server/pm/InstallArgs.java
index dd96a2b..cc6bb00 100644
--- a/services/core/java/com/android/server/pm/InstallArgs.java
+++ b/services/core/java/com/android/server/pm/InstallArgs.java
@@ -67,7 +67,8 @@
// The list of instruction sets supported by this app. This is currently
// only used during the rmdex() phase to clean up resources. We can get rid of this
// if we move dex files under the common app path.
- @Nullable String[] mInstructionSets;
+ @Nullable
+ final String[] mInstructionSets;
InstallArgs(OriginInfo originInfo, MoveInfo moveInfo, IPackageInstallObserver2 observer,
int installFlags, int developmentInstallFlags, InstallSource installSource,
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index be4fb5c..fc83120 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -153,7 +153,7 @@
private int[] mUpdateBroadcastInstantUserIds = EMPTY_INT_ARRAY;
@NonNull
- private ArrayList<String> mWarnings = new ArrayList<>();
+ private final ArrayList<String> mWarnings = new ArrayList<>();
// New install
InstallRequest(InstallingSession params) {
diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java
index ca8dc29..187cada 100644
--- a/services/core/java/com/android/server/pm/InstallingSession.java
+++ b/services/core/java/com/android/server/pm/InstallingSession.java
@@ -68,7 +68,7 @@
final MoveInfo mMoveInfo;
final IPackageInstallObserver2 mObserver;
int mInstallFlags;
- int mDevelopmentInstallFlags;
+ final int mDevelopmentInstallFlags;
@NonNull
final InstallSource mInstallSource;
final String mVolumeUuid;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 8b82a1c..3f4cc4a 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -233,7 +233,8 @@
final LauncherAppsServiceInternal mInternal;
@NonNull
- private final RemoteCallbackList<IDumpCallback> mDumpCallbacks = new RemoteCallbackList<>();
+ private final RemoteCallbackList<IDumpCallback> mDumpCallbacks =
+ new RemoteCallbackList<>();
public LauncherAppsImpl(Context context) {
mContext = context;
@@ -2374,8 +2375,8 @@
class PackageLoadingProgressCallback extends
PackageManagerInternal.InstalledLoadingProgressCallback {
- private String mPackageName;
- private UserHandle mUser;
+ private final String mPackageName;
+ private final UserHandle mUser;
PackageLoadingProgressCallback(String packageName, UserHandle user) {
super(mCallbackHandler);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a4d8632..98eee4d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -1867,7 +1867,8 @@
}
static class ParentChildSessionMap {
- private TreeMap<PackageInstallerSession, TreeSet<PackageInstallerSession>> mSessionMap;
+ private final TreeMap<PackageInstallerSession, TreeSet<PackageInstallerSession>>
+ mSessionMap;
private final Comparator<PackageInstallerSession> mSessionCreationComparator =
Comparator.comparingLong(
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1be28ca..4b466be 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -491,7 +491,7 @@
@GuardedBy("mLock")
private SigningDetails mSigningDetails;
@GuardedBy("mLock")
- private SparseArray<PackageInstallerSession> mChildSessions = new SparseArray<>();
+ private final SparseArray<PackageInstallerSession> mChildSessions = new SparseArray<>();
@GuardedBy("mLock")
private int mParentSessionId;
@@ -535,7 +535,7 @@
}
@GuardedBy("mLock")
- private ArraySet<FileEntry> mFiles = new ArraySet<>();
+ private final ArraySet<FileEntry> mFiles = new ArraySet<>();
static class PerFileChecksum {
private final Checksum[] mChecksums;
@@ -556,7 +556,7 @@
}
@GuardedBy("mLock")
- private ArrayMap<String, PerFileChecksum> mChecksums = new ArrayMap<>();
+ private final ArrayMap<String, PerFileChecksum> mChecksums = new ArrayMap<>();
@GuardedBy("mLock")
private boolean mSessionApplied;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index 9428ef6..655b9c9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -60,7 +60,7 @@
public IncrementalManager incrementalManager;
public PackageInstallerService installerService;
public InstantAppRegistry instantAppRegistry;
- public ChangedPackagesTracker changedPackagesTracker = new ChangedPackagesTracker();
+ public final ChangedPackagesTracker changedPackagesTracker = new ChangedPackagesTracker();
public InstantAppResolverConnection instantAppResolverConnection;
public ComponentName instantAppResolverSettingsComponent;
public boolean isPreNmr1Upgrade;
@@ -118,7 +118,7 @@
public SuspendPackageHelper suspendPackageHelper;
public DistractingPackageHelper distractingPackageHelper;
public StorageEventHelper storageEventHelper;
- public Set<String> initialNonStoppedSystemPackages = new ArraySet<>();
+ public final Set<String> initialNonStoppedSystemPackages = new ArraySet<>();
public boolean shouldStopSystemPackagesByDefault;
public FreeStorageHelper freeStorageHelper;
public PackageMonitorCallbackHelper packageMonitorCallbackHelper;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index d4abad8..6f45d2b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2364,7 +2364,7 @@
private boolean mSuccess = false;
private int mErrCode = -1;
private ParcelFileDescriptor mProfileReadFd = null;
- private CountDownLatch mDoneSignal = new CountDownLatch(1);
+ private final CountDownLatch mDoneSignal = new CountDownLatch(1);
@Override
public void onSuccess(ParcelFileDescriptor profileReadFd) {
@@ -5186,7 +5186,7 @@
private static class LocalIntentReceiver {
private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>();
- private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
+ private final IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
@Override
public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
index a09e713..c829e1c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -148,7 +148,8 @@
private final byte[] mData;
private final String mSalt;
- private static AtomicLong sGlobalSalt = new AtomicLong((new SecureRandom()).nextLong());
+ private static final AtomicLong sGlobalSalt =
+ new AtomicLong((new SecureRandom()).nextLong());
private static Long nextGlobalSalt() {
return sGlobalSalt.incrementAndGet();
}
diff --git a/services/core/java/com/android/server/pm/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java
index 5507e7c..18caafd 100644
--- a/services/core/java/com/android/server/pm/PreferredComponent.java
+++ b/services/core/java/com/android/server/pm/PreferredComponent.java
@@ -48,7 +48,7 @@
public final int mMatch;
public final ComponentName mComponent;
// Whether this is to be the one that's always chosen. If false, it's the most recently chosen.
- public boolean mAlways;
+ public final boolean mAlways;
final String[] mSetPackages;
final String[] mSetClasses;
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index cf5aa7b..e667bfe 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -68,12 +68,12 @@
// All policy stanzas read from mac_permissions.xml. This is also the lock
// to synchronize access during policy load and access attempts.
- private static List<Policy> sPolicies = new ArrayList<>();
+ private static final List<Policy> sPolicies = new ArrayList<>();
/** Whether or not the policy files have been read */
private static boolean sPolicyRead;
/** Required MAC permissions files */
- private static List<File> sMacPermissions = new ArrayList<>();
+ private static final List<File> sMacPermissions = new ArrayList<>();
private static final String DEFAULT_SEINFO = "default";
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 440823c..6338965 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3944,9 +3944,9 @@
mDisabledSysPackages.put(name, ps);
}
- private static int PRE_M_APP_INFO_FLAG_HIDDEN = 1<<27;
- private static int PRE_M_APP_INFO_FLAG_CANT_SAVE_STATE = 1<<28;
- private static int PRE_M_APP_INFO_FLAG_PRIVILEGED = 1<<30;
+ private static final int PRE_M_APP_INFO_FLAG_HIDDEN = 1 << 27;
+ private static final int PRE_M_APP_INFO_FLAG_CANT_SAVE_STATE = 1 << 28;
+ private static final int PRE_M_APP_INFO_FLAG_PRIVILEGED = 1 << 30;
private void readPackageLPw(TypedXmlPullParser parser, List<UserInfo> users,
ArrayMap<String, Long> originalFirstInstallTimes)
@@ -5846,7 +5846,7 @@
@GuardedBy("mLock")
// Tracking the mutations that haven't yet been written to legacy state.
// This avoids unnecessary work when writing settings for multiple users.
- private AtomicBoolean mIsLegacyPermissionStateStale = new AtomicBoolean(false);
+ private final AtomicBoolean mIsLegacyPermissionStateStale = new AtomicBoolean(false);
@GuardedBy("mLock")
// The mapping keys are user ids.
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 8667888..12115af 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -53,7 +53,7 @@
protected ShortcutUser mShortcutUser;
@GuardedBy("mLock")
- protected ShortcutBitmapSaver mShortcutBitmapSaver;
+ protected final ShortcutBitmapSaver mShortcutBitmapSaver;
protected final Object mLock = new Object();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index c6aba2a..3adeb4b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -296,24 +296,26 @@
private final Object mNonPersistentUsersLock = new Object();
private final Object mWtfLock = new Object();
- private static List<ResolveInfo> EMPTY_RESOLVE_INFO = new ArrayList<>(0);
+ private static final List<ResolveInfo> EMPTY_RESOLVE_INFO = new ArrayList<>(0);
// Temporarily reverted to anonymous inner class form due to: b/32554459
- private static Predicate<ResolveInfo> ACTIVITY_NOT_EXPORTED = new Predicate<ResolveInfo>() {
- public boolean test(ResolveInfo ri) {
- return !ri.activityInfo.exported;
- }
- };
+ private static final Predicate<ResolveInfo> ACTIVITY_NOT_EXPORTED =
+ new Predicate<ResolveInfo>() {
+ public boolean test(ResolveInfo ri) {
+ return !ri.activityInfo.exported;
+ }
+ };
- private static Predicate<ResolveInfo> ACTIVITY_NOT_INSTALLED = (ri) ->
+ private static final Predicate<ResolveInfo> ACTIVITY_NOT_INSTALLED = (ri) ->
!isInstalled(ri.activityInfo);
// Temporarily reverted to anonymous inner class form due to: b/32554459
- private static Predicate<PackageInfo> PACKAGE_NOT_INSTALLED = new Predicate<PackageInfo>() {
- public boolean test(PackageInfo pi) {
- return !isInstalled(pi);
- }
- };
+ private static final Predicate<PackageInfo> PACKAGE_NOT_INSTALLED =
+ new Predicate<PackageInfo>() {
+ public boolean test(PackageInfo pi) {
+ return !isInstalled(pi);
+ }
+ };
private final Handler mHandler;
@@ -4656,8 +4658,8 @@
private boolean mDumpFiles = false;
private boolean mDumpDetails = true;
- private List<Pattern> mPackagePatterns = new ArrayList<>();
- private List<Integer> mUsers = new ArrayList<>();
+ private final List<Pattern> mPackagePatterns = new ArrayList<>();
+ private final List<Integer> mUsers = new ArrayList<>();
void addPackageRegex(String regex) {
mPackagePatterns.add(Pattern.compile(regex));
diff --git a/services/core/java/com/android/server/pm/SnapshotStatistics.java b/services/core/java/com/android/server/pm/SnapshotStatistics.java
index e04a1e5..31541d0 100644
--- a/services/core/java/com/android/server/pm/SnapshotStatistics.java
+++ b/services/core/java/com/android/server/pm/SnapshotStatistics.java
@@ -157,12 +157,12 @@
private static class BinMap {
// The number of bins
- private int mCount;
+ private final int mCount;
// The maximum mapped value. Values at or above this are mapped to the
// top bin.
- private int mMaxBin;
+ private final int mMaxBin;
// A copy of the original key
- private int[] mUserKey;
+ private final int[] mUserKey;
/**
* Create a bin map. The input is an array of integers, which must be
@@ -232,13 +232,13 @@
* The build-time histogram. The total number of rebuilds is the sum over the
* histogram entries.
*/
- public int[] mTimes;
+ public final int[] mTimes;
/**
* The reuse histogram. The total number of snapshot uses is the sum over the
* histogram entries.
*/
- public int[] mUsed;
+ public final int[] mUsed;
/**
* The total number of rebuilds. This could be computed by summing over the use
@@ -477,12 +477,12 @@
/**
* Long statistics. These roll over approximately one day.
*/
- private Stats[] mLong;
+ private final Stats[] mLong;
/**
* Short statistics. These roll over approximately every minute;
*/
- private Stats[] mShort;
+ private final Stats[] mShort;
/**
* The time of last logging to the FrameworkStatsLog.
diff --git a/services/core/java/com/android/server/pm/UserJourneyLogger.java b/services/core/java/com/android/server/pm/UserJourneyLogger.java
index 895edce..651578d 100644
--- a/services/core/java/com/android/server/pm/UserJourneyLogger.java
+++ b/services/core/java/com/android/server/pm/UserJourneyLogger.java
@@ -586,7 +586,7 @@
public final long mSessionId;
@UserJourney
public final int mJourney;
- public long mStartTimeInMills;
+ public final long mStartTimeInMills;
@VisibleForTesting
public UserJourneySession(long sessionId, @UserJourney int journey) {
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 6e738da..78c13f8 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -119,10 +119,10 @@
private final int mCriticalBatteryLevel;
// Possible outcomes of a dex search.
- private static int DEX_SEARCH_NOT_FOUND = 0; // dex file not found
- private static int DEX_SEARCH_FOUND_PRIMARY = 1; // dex file is the primary/base apk
- private static int DEX_SEARCH_FOUND_SPLIT = 2; // dex file is a split apk
- private static int DEX_SEARCH_FOUND_SECONDARY = 3; // dex file is a secondary dex
+ private static final int DEX_SEARCH_NOT_FOUND = 0; // dex file not found
+ private static final int DEX_SEARCH_FOUND_PRIMARY = 1; // dex file is the primary/base apk
+ private static final int DEX_SEARCH_FOUND_SPLIT = 2; // dex file is a split apk
+ private static final int DEX_SEARCH_FOUND_SECONDARY = 3; // dex file is a secondary dex
public DexManager(Context context, PackageDexOptimizer pdo, Installer installer,
Object installLock, DynamicCodeLogger dynamicCodeLogger) {
@@ -959,8 +959,8 @@
* Convenience class to store ownership search results.
*/
private class DexSearchResult {
- private String mOwningPackageName;
- private int mOutcome;
+ private final String mOwningPackageName;
+ private final int mOutcome;
public DexSearchResult(String owningPackageName, int outcome) {
this.mOwningPackageName = owningPackageName;
diff --git a/services/core/java/com/android/server/pm/parsing/PackageCacher.java b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
index d3a64bb..2ab7db4 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageCacher.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
@@ -49,7 +49,7 @@
public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
@NonNull
- private File mCacheDir;
+ private final File mCacheDir;
public PackageCacher(@NonNull File cacheDir) {
this.mCacheDir = cacheDir;
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 9e20805..c26cf1c 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -1132,7 +1132,7 @@
*/
public static class CachedApplicationInfoGenerator {
// Map from a package name to the corresponding app info.
- private ArrayMap<String, ApplicationInfo> mCache = new ArrayMap<>();
+ private final ArrayMap<String, ApplicationInfo> mCache = new ArrayMap<>();
/**
* {@link PackageInfoUtils#generateApplicationInfo} with a cache.
diff --git a/services/core/java/com/android/server/pm/parsing/PackageParser2.java b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
index d82a500..3b10c7f 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageParser2.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
@@ -96,19 +96,19 @@
private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
- private ThreadLocal<ApplicationInfo> mSharedAppInfo =
+ private final ThreadLocal<ApplicationInfo> mSharedAppInfo =
ThreadLocal.withInitial(() -> {
ApplicationInfo appInfo = new ApplicationInfo();
appInfo.uid = -1; // Not a valid UID since the app will not be installed yet
return appInfo;
});
- private ThreadLocal<ParseTypeImpl> mSharedResult;
+ private final ThreadLocal<ParseTypeImpl> mSharedResult;
@Nullable
protected PackageCacher mCacher;
- private ParsingPackageUtils parsingUtils;
+ private final ParsingPackageUtils parsingUtils;
public PackageParser2(String[] separateProcesses, DisplayMetrics displayMetrics,
@Nullable File cacheDir, @NonNull Callback callback) {
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index 056aae4..75dd67d 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -113,21 +113,21 @@
private static final SparseArray<int[]> EMPTY_INT_ARRAY_SPARSE_ARRAY = new SparseArray<>();
private static final Comparator<ParsedMainComponent> ORDER_COMPARATOR =
(first, second) -> Integer.compare(second.getOrder(), first.getOrder());
- public static Parcelling.BuiltIn.ForBoolean sForBoolean = Parcelling.Cache.getOrCreate(
+ public static final Parcelling.BuiltIn.ForBoolean sForBoolean = Parcelling.Cache.getOrCreate(
Parcelling.BuiltIn.ForBoolean.class);
- public static ForInternedString sForInternedString = Parcelling.Cache.getOrCreate(
+ public static final ForInternedString sForInternedString = Parcelling.Cache.getOrCreate(
ForInternedString.class);
- public static Parcelling.BuiltIn.ForInternedStringArray sForInternedStringArray = Parcelling.Cache.getOrCreate(
- Parcelling.BuiltIn.ForInternedStringArray.class);
- public static Parcelling.BuiltIn.ForInternedStringList sForInternedStringList = Parcelling.Cache.getOrCreate(
- Parcelling.BuiltIn.ForInternedStringList.class);
- public static Parcelling.BuiltIn.ForInternedStringValueMap sForInternedStringValueMap =
+ public static final Parcelling.BuiltIn.ForInternedStringArray sForInternedStringArray =
+ Parcelling.Cache.getOrCreate(Parcelling.BuiltIn.ForInternedStringArray.class);
+ public static final Parcelling.BuiltIn.ForInternedStringList sForInternedStringList =
+ Parcelling.Cache.getOrCreate(Parcelling.BuiltIn.ForInternedStringList.class);
+ public static final Parcelling.BuiltIn.ForInternedStringValueMap sForInternedStringValueMap =
Parcelling.Cache.getOrCreate(Parcelling.BuiltIn.ForInternedStringValueMap.class);
- public static Parcelling.BuiltIn.ForStringSet sForStringSet = Parcelling.Cache.getOrCreate(
- Parcelling.BuiltIn.ForStringSet.class);
- public static Parcelling.BuiltIn.ForInternedStringSet sForInternedStringSet =
+ public static final Parcelling.BuiltIn.ForStringSet sForStringSet =
+ Parcelling.Cache.getOrCreate(Parcelling.BuiltIn.ForStringSet.class);
+ public static final Parcelling.BuiltIn.ForInternedStringSet sForInternedStringSet =
Parcelling.Cache.getOrCreate(Parcelling.BuiltIn.ForInternedStringSet.class);
- protected static ParsingUtils.StringPairListParceler sForIntentInfoPairs =
+ protected static final ParsingUtils.StringPairListParceler sForIntentInfoPairs =
new ParsingUtils.StringPairListParceler();
protected int versionCode;
protected int versionCodeMajor;
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index d6a7dc6..6f6bb45 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1748,14 +1748,14 @@
*/
private class DelayingPackageManagerCache extends PackageManagerWrapper {
/** uid -> permission -> isGranted, flags */
- private SparseArray<ArrayMap<String, PermissionState>> mDelayedPermissionState =
+ private final SparseArray<ArrayMap<String, PermissionState>> mDelayedPermissionState =
new SparseArray<>();
/** userId -> context */
- private SparseArray<Context> mUserContexts = new SparseArray<>();
+ private final SparseArray<Context> mUserContexts = new SparseArray<>();
/** Permission name -> info */
- private ArrayMap<String, PermissionInfo> mPermissionInfos = new ArrayMap<>();
+ private final ArrayMap<String, PermissionInfo> mPermissionInfos = new ArrayMap<>();
/** Package name -> info */
- private ArrayMap<String, PackageInfo> mPackageInfos = new ArrayMap<>();
+ private final ArrayMap<String, PackageInfo> mPackageInfos = new ArrayMap<>();
/**
* Apply the cached state
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionImpl.java b/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionImpl.java
index 70986c3..4c831d3 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionImpl.java
@@ -41,7 +41,8 @@
public class ParsedPermissionImpl extends ParsedComponentImpl implements ParsedPermission,
Parcelable {
- private static ForStringSet sForStringSet = Parcelling.Cache.getOrCreate(ForStringSet.class);
+ private static final ForStringSet sForStringSet =
+ Parcelling.Cache.getOrCreate(ForStringSet.class);
@Nullable
private String backgroundPermission;
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 8240c47..061698a 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -328,11 +328,11 @@
return input.success(pkg);
}
- private String[] mSeparateProcesses;
- private DisplayMetrics mDisplayMetrics;
+ private final String[] mSeparateProcesses;
+ private final DisplayMetrics mDisplayMetrics;
@NonNull
- private List<PermissionManager.SplitPermissionInfo> mSplitPermissionInfos;
- private Callback mCallback;
+ private final List<PermissionManager.SplitPermissionInfo> mSplitPermissionInfos;
+ private final Callback mCallback;
public ParsingPackageUtils(String[] separateProcesses, DisplayMetrics displayMetrics,
@NonNull List<PermissionManager.SplitPermissionInfo> splitPermissions,
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
index fac681a..0ceda42 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -951,7 +951,7 @@
extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
@NonNull
- private UserNeedsBadgingCache mUserNeedsBadging;
+ private final UserNeedsBadgingCache mUserNeedsBadging;
// Default constructor
ActivityIntentResolver(@NonNull UserManagerService userManager,
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
index 9115775..80cde73 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
@@ -68,7 +68,7 @@
protected ArrayMap<String, ParsedProvider> mProvidersByAuthority;
@NonNull
- protected UserManagerService mUserManager;
+ protected final UserManagerService mUserManager;
protected ComponentResolverBase(@NonNull UserManagerService userManager) {
mUserManager = userManager;
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index 11f62e9..3d4d4ec 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -2005,9 +2005,9 @@
private static class GetAttachedResult {
@Nullable
- private DomainVerificationPkgState mPkgState;
+ private final DomainVerificationPkgState mPkgState;
- private int mErrorCode;
+ private final int mErrorCode;
GetAttachedResult(@Nullable DomainVerificationPkgState pkgState, int errorCode) {
mPkgState = pkgState;
diff --git a/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java b/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java
index 6c56360..d71dbbb 100644
--- a/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java
+++ b/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java
@@ -40,7 +40,7 @@
private final String mPackageName;
@NonNull
- private UUID mId;
+ private final UUID mId;
/**
* Whether or not the package declares any autoVerify domains. This is separate from an empty
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
index a388932..b8e581f 100644
--- a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
@@ -592,6 +592,10 @@
public void dumpCpuPowerBracketsLocked(PrintWriter pw) {
ensureInitialized();
+ if (mLayout == null) {
+ return;
+ }
+
pw.println("CPU power brackets; cluster/freq in MHz(avg current in mA):");
for (int bracket = 0; bracket < mLayout.getCpuPowerBracketCount(); bracket++) {
pw.print(" ");
diff --git a/services/core/jni/tvinput/JTvInputHal.cpp b/services/core/jni/tvinput/JTvInputHal.cpp
index dc05462..80427b3 100644
--- a/services/core/jni/tvinput/JTvInputHal.cpp
+++ b/services/core/jni/tvinput/JTvInputHal.cpp
@@ -25,7 +25,7 @@
mThiz = env->NewWeakGlobalRef(thiz);
mTvInput = tvInput;
mLooper = looper;
- mTvInputCallback = ::ndk::SharedRefBase::make<TvInputCallback>(this);
+ mTvInputCallback = std::shared_ptr<TvInputCallbackWrapper>(new TvInputCallbackWrapper(this));
mTvInput->setCallback(mTvInputCallback);
}
@@ -443,18 +443,23 @@
}
}
-JTvInputHal::TvInputCallback::TvInputCallback(JTvInputHal* hal) {
+JTvInputHal::TvInputCallbackWrapper::TvInputCallbackWrapper(JTvInputHal* hal) {
+ aidlTvInputCallback = ::ndk::SharedRefBase::make<AidlTvInputCallback>(hal);
+ hidlTvInputCallback = sp<HidlTvInputCallback>::make(hal);
+}
+
+JTvInputHal::AidlTvInputCallback::AidlTvInputCallback(JTvInputHal* hal) {
mHal = hal;
}
-::ndk::ScopedAStatus JTvInputHal::TvInputCallback::notify(const AidlTvInputEvent& event) {
+::ndk::ScopedAStatus JTvInputHal::AidlTvInputCallback::notify(const AidlTvInputEvent& event) {
mHal->mLooper->sendMessage(new NotifyHandler(mHal,
TvInputEventWrapper::createEventWrapper(event)),
static_cast<int>(event.type));
return ::ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus JTvInputHal::TvInputCallback::notifyTvMessageEvent(
+::ndk::ScopedAStatus JTvInputHal::AidlTvInputCallback::notifyTvMessageEvent(
const AidlTvMessageEvent& event) {
const std::string DEVICE_ID_SUBTYPE = "device_id";
::ndk::ScopedAStatus status = ::ndk::ScopedAStatus::ok();
@@ -487,11 +492,14 @@
: mIsHidl(false), mAidlTvInput(aidlTvInput) {}
::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::setCallback(
- const std::shared_ptr<TvInputCallback>& in_callback) {
+ const std::shared_ptr<TvInputCallbackWrapper>& in_callback) {
if (mIsHidl) {
- return hidlSetCallback(in_callback);
+ in_callback->aidlTvInputCallback = nullptr;
+ return hidlSetCallback(in_callback == nullptr ? nullptr : in_callback->hidlTvInputCallback);
} else {
- return mAidlTvInput->setCallback(in_callback);
+ in_callback->hidlTvInputCallback = nullptr;
+ return mAidlTvInput->setCallback(in_callback == nullptr ? nullptr
+ : in_callback->aidlTvInputCallback);
}
}
diff --git a/services/core/jni/tvinput/JTvInputHal.h b/services/core/jni/tvinput/JTvInputHal.h
index 6026a10..2ef94ac 100644
--- a/services/core/jni/tvinput/JTvInputHal.h
+++ b/services/core/jni/tvinput/JTvInputHal.h
@@ -168,23 +168,39 @@
JTvInputHal* mHal;
};
- class TvInputCallback : public HidlITvInputCallback, public BnTvInputCallback {
+ class AidlTvInputCallback : public BnTvInputCallback {
public:
- explicit TvInputCallback(JTvInputHal* hal);
+ explicit AidlTvInputCallback(JTvInputHal* hal);
::ndk::ScopedAStatus notify(const AidlTvInputEvent& event) override;
::ndk::ScopedAStatus notifyTvMessageEvent(const AidlTvMessageEvent& event) override;
+
+ private:
+ JTvInputHal* mHal;
+ };
+
+ class HidlTvInputCallback : public HidlITvInputCallback {
+ public:
+ explicit HidlTvInputCallback(JTvInputHal* hal);
Return<void> notify(const HidlTvInputEvent& event) override;
private:
JTvInputHal* mHal;
};
+ class TvInputCallbackWrapper {
+ public:
+ explicit TvInputCallbackWrapper(JTvInputHal* hal);
+ std::shared_ptr<AidlTvInputCallback> aidlTvInputCallback;
+ sp<HidlTvInputCallback> hidlTvInputCallback;
+ };
+
class ITvInputWrapper {
public:
ITvInputWrapper(std::shared_ptr<AidlITvInput>& aidlTvInput);
ITvInputWrapper(sp<HidlITvInput>& hidlTvInput);
- ::ndk::ScopedAStatus setCallback(const std::shared_ptr<TvInputCallback>& in_callback);
+ ::ndk::ScopedAStatus setCallback(
+ const std::shared_ptr<TvInputCallbackWrapper>& in_callback);
::ndk::ScopedAStatus getStreamConfigurations(int32_t in_deviceId,
std::vector<AidlTvStreamConfig>* _aidl_return);
::ndk::ScopedAStatus openStream(int32_t in_deviceId, int32_t in_streamId,
@@ -198,7 +214,7 @@
::ndk::ScopedAStatus getAidlInterfaceVersion(int32_t* _aidl_return);
private:
- ::ndk::ScopedAStatus hidlSetCallback(const std::shared_ptr<TvInputCallback>& in_callback);
+ ::ndk::ScopedAStatus hidlSetCallback(const sp<HidlTvInputCallback>& in_callback);
::ndk::ScopedAStatus hidlGetStreamConfigurations(
int32_t in_deviceId, std::vector<AidlTvStreamConfig>* _aidl_return);
::ndk::ScopedAStatus hidlOpenStream(int32_t in_deviceId, int32_t in_streamId,
@@ -229,7 +245,7 @@
KeyedVector<int, KeyedVector<int, Connection> > mConnections;
std::shared_ptr<ITvInputWrapper> mTvInput;
- std::shared_ptr<TvInputCallback> mTvInputCallback;
+ std::shared_ptr<TvInputCallbackWrapper> mTvInputCallback;
};
} // namespace android
diff --git a/services/core/jni/tvinput/TvInputHal_hidl.cpp b/services/core/jni/tvinput/TvInputHal_hidl.cpp
index 37cf844..cdd9266 100644
--- a/services/core/jni/tvinput/TvInputHal_hidl.cpp
+++ b/services/core/jni/tvinput/TvInputHal_hidl.cpp
@@ -59,7 +59,11 @@
return event;
}
-Return<void> JTvInputHal::TvInputCallback::notify(const HidlTvInputEvent& event) {
+JTvInputHal::HidlTvInputCallback::HidlTvInputCallback(JTvInputHal* hal) {
+ mHal = hal;
+}
+
+Return<void> JTvInputHal::HidlTvInputCallback::notify(const HidlTvInputEvent& event) {
mHal->mLooper->sendMessage(new NotifyHandler(mHal,
TvInputEventWrapper::createEventWrapper(event)),
static_cast<int>(event.type));
@@ -70,9 +74,8 @@
: mIsHidl(true), mHidlTvInput(hidlTvInput) {}
::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::hidlSetCallback(
- const std::shared_ptr<TvInputCallback>& in_callback) {
- mHidlTvInput->setCallback(in_callback == nullptr ? nullptr
- : sp<TvInputCallback>(in_callback.get()));
+ const sp<HidlTvInputCallback>& in_callback) {
+ mHidlTvInput->setCallback(in_callback);
return ::ndk::ScopedAStatus::ok();
}
diff --git a/services/tests/servicestests/src/com/android/server/pdb/PersistentDataBlockServiceTest.java b/services/tests/servicestests/src/com/android/server/pdb/PersistentDataBlockServiceTest.java
new file mode 100644
index 0000000..f537efd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pdb/PersistentDataBlockServiceTest.java
@@ -0,0 +1,552 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pdb;
+
+import static com.android.server.pdb.PersistentDataBlockService.DIGEST_SIZE_BYTES;
+import static com.android.server.pdb.PersistentDataBlockService.MAX_DATA_BLOCK_SIZE;
+import static com.android.server.pdb.PersistentDataBlockService.MAX_FRP_CREDENTIAL_HANDLE_SIZE;
+import static com.android.server.pdb.PersistentDataBlockService.MAX_TEST_MODE_DATA_SIZE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.junit.Assert.assertThrows;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.service.persistentdata.IPersistentDataBlockService;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.StandardOpenOption;
+
+@RunWith(JUnitParamsRunner.class)
+public class PersistentDataBlockServiceTest {
+ private static final String TAG = "PersistentDataBlockServiceTest";
+
+ private static final byte[] SMALL_DATA = "data to write".getBytes();
+ private static final byte[] ANOTHER_SMALL_DATA = "something else".getBytes();
+
+ private Context mContext;
+ private PersistentDataBlockService mPdbService;
+ private IPersistentDataBlockService mInterface;
+ private PersistentDataBlockManagerInternal mInternalInterface;
+ private File mDataBlockFile;
+ private String mOemUnlockPropertyValue;
+
+ @Mock private UserManager mUserManager;
+
+ private class FakePersistentDataBlockService extends PersistentDataBlockService {
+ FakePersistentDataBlockService(Context context, String dataBlockFile,
+ long blockDeviceSize) {
+ super(context, /* isFileBacked */ true, dataBlockFile, blockDeviceSize);
+ }
+
+ @Override
+ void setProperty(String key, String value) {
+ // Override to capture the value instead of actually setting the property.
+ assertThat(key).isEqualTo("sys.oem_unlock_allowed");
+ mOemUnlockPropertyValue = value;
+ }
+ }
+
+ @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mDataBlockFile = mTemporaryFolder.newFile();
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mPdbService = new FakePersistentDataBlockService(mContext, mDataBlockFile.getPath(),
+ /* blockDeviceSize */ -1);
+ mPdbService.setAllowedUid(Binder.getCallingUid());
+ mPdbService.formatPartitionLocked(/* setOemUnlockEnabled */ false);
+ mInterface = mPdbService.getInterfaceForTesting();
+ mInternalInterface = mPdbService.getInternalInterfaceForTesting();
+
+ when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
+ }
+
+ abstract static class Block {
+ public PersistentDataBlockService service;
+
+ abstract int write(byte[] data) throws RemoteException;
+ abstract byte[] read() throws RemoteException;
+ }
+
+ /**
+ * Configuration for parameterizing tests, including the block name, maximum block size, and
+ * a block implementation for the read/write operations.
+ */
+ public Object[][] getTestParametersForBlocks() {
+ return new Object[][] {
+ {
+ new Block() {
+ @Override public int write(byte[] data) throws RemoteException {
+ return service.getInterfaceForTesting().write(data);
+ }
+
+ @Override public byte[] read() throws RemoteException {
+ return service.getInterfaceForTesting().read();
+ }
+ },
+ },
+ {
+ new Block() {
+ @Override public int write(byte[] data) {
+ service.getInternalInterfaceForTesting().setFrpCredentialHandle(data);
+ // The written size isn't returned. Pretend it's fully written in the
+ // test for now.
+ return data.length;
+ }
+
+ @Override public byte[] read() {
+ return service.getInternalInterfaceForTesting().getFrpCredentialHandle();
+ }
+ },
+ },
+ {
+ new Block() {
+ @Override public int write(byte[] data) {
+ service.getInternalInterfaceForTesting().setTestHarnessModeData(data);
+ // The written size isn't returned. Pretend it's fully written in the
+ // test for now.
+ return data.length;
+ }
+
+ @Override public byte[] read() {
+ return service.getInternalInterfaceForTesting().getTestHarnessModeData();
+ }
+ },
+ },
+ };
+ }
+
+ @Test
+ @Parameters(method = "getTestParametersForBlocks")
+ public void writeThenRead(Block block) throws Exception {
+ block.service = mPdbService;
+ assertThat(block.write(SMALL_DATA)).isEqualTo(SMALL_DATA.length);
+ assertThat(block.read()).isEqualTo(SMALL_DATA);
+ }
+
+ @Test
+ @Parameters(method = "getTestParametersForBlocks")
+ public void writeWhileAlreadyCorrupted(Block block) throws Exception {
+ block.service = mPdbService;
+ assertThat(block.write(SMALL_DATA)).isEqualTo(SMALL_DATA.length);
+ assertThat(block.read()).isEqualTo(SMALL_DATA);
+
+ tamperWithDigest();
+
+ // In the currently implementation, expect the write to not trigger formatting.
+ assertThat(block.write(ANOTHER_SMALL_DATA)).isEqualTo(ANOTHER_SMALL_DATA.length);
+ }
+
+ @Test
+ public void frpWriteOutOfBound() throws Exception {
+ byte[] maxData = new byte[mPdbService.getMaximumFrpDataSize()];
+ assertThat(mInterface.write(maxData)).isEqualTo(maxData.length);
+
+ byte[] overflowData = new byte[mPdbService.getMaximumFrpDataSize() + 1];
+ assertThat(mInterface.write(overflowData)).isLessThan(0);
+ }
+
+ @Test
+ public void frpCredentialWriteOutOfBound() throws Exception {
+ byte[] maxData = new byte[MAX_FRP_CREDENTIAL_HANDLE_SIZE];
+ mInternalInterface.setFrpCredentialHandle(maxData);
+
+ byte[] overflowData = new byte[MAX_FRP_CREDENTIAL_HANDLE_SIZE + 1];
+ assertThrows(IllegalArgumentException.class, () ->
+ mInternalInterface.setFrpCredentialHandle(overflowData));
+ }
+
+ @Test
+ public void testHardnessWriteOutOfBound() throws Exception {
+ byte[] maxData = new byte[MAX_TEST_MODE_DATA_SIZE];
+ mInternalInterface.setTestHarnessModeData(maxData);
+
+ byte[] overflowData = new byte[MAX_TEST_MODE_DATA_SIZE + 1];
+ assertThrows(IllegalArgumentException.class, () ->
+ mInternalInterface.setTestHarnessModeData(overflowData));
+ }
+
+ @Test
+ public void readCorruptedFrpData() throws Exception {
+ assertThat(mInterface.write(SMALL_DATA)).isEqualTo(SMALL_DATA.length);
+ assertThat(mInterface.read()).isEqualTo(SMALL_DATA);
+
+ tamperWithDigest();
+
+ // Expect the read to trigger formatting, resulting in reading empty data.
+ assertThat(mInterface.read()).hasLength(0);
+ }
+
+ @Test
+ public void readCorruptedFrpCredentialData() throws Exception {
+ mInternalInterface.setFrpCredentialHandle(SMALL_DATA);
+ assertThat(mInternalInterface.getFrpCredentialHandle()).isEqualTo(SMALL_DATA);
+
+ tamperWithDigest();
+
+ assertThrows(IllegalStateException.class, () ->
+ mInternalInterface.getFrpCredentialHandle());
+ }
+
+ @Test
+ public void readCorruptedTestHarnessData() throws Exception {
+ mInternalInterface.setTestHarnessModeData(SMALL_DATA);
+ assertThat(mInternalInterface.getTestHarnessModeData()).isEqualTo(SMALL_DATA);
+
+ tamperWithDigest();
+
+ assertThrows(IllegalStateException.class, () ->
+ mInternalInterface.getTestHarnessModeData());
+ }
+
+ @Test
+ public void nullWrite() throws Exception {
+ assertThrows(NullPointerException.class, () -> mInterface.write(null));
+ mInternalInterface.setFrpCredentialHandle(null); // no exception
+ mInternalInterface.setTestHarnessModeData(null); // no exception
+ }
+
+ @Test
+ public void emptyDataWrite() throws Exception {
+ var empty = new byte[0];
+ assertThat(mInterface.write(empty)).isEqualTo(0);
+
+ assertThrows(IllegalArgumentException.class, () ->
+ mInternalInterface.setFrpCredentialHandle(empty));
+ assertThrows(IllegalArgumentException.class, () ->
+ mInternalInterface.setTestHarnessModeData(empty));
+ }
+
+ @Test
+ public void frpWriteMoreThan100K() throws Exception {
+ File dataBlockFile = mTemporaryFolder.newFile();
+ PersistentDataBlockService pdbService = new FakePersistentDataBlockService(mContext,
+ dataBlockFile.getPath(), /* blockDeviceSize */ 128 * 1000);
+ pdbService.setAllowedUid(Binder.getCallingUid());
+ pdbService.formatPartitionLocked(/* setOemUnlockEnabled */ false);
+
+ IPersistentDataBlockService service = pdbService.getInterfaceForTesting();
+ int maxDataSize = (int) service.getMaximumDataBlockSize();
+ assertThat(service.write(new byte[maxDataSize])).isEqualTo(maxDataSize);
+ assertThat(service.write(new byte[maxDataSize + 1])).isEqualTo(-MAX_DATA_BLOCK_SIZE);
+ }
+
+ @Test
+ public void frpBlockReadWriteWithoutPermission() throws Exception {
+ mPdbService.setAllowedUid(Binder.getCallingUid() + 1); // unexpected uid
+ assertThrows(SecurityException.class, () -> mInterface.write(SMALL_DATA));
+ assertThrows(SecurityException.class, () -> mInterface.read());
+ }
+
+ @Test
+ public void getMaximumDataBlockSizeDenied() throws Exception {
+ mPdbService.setAllowedUid(Binder.getCallingUid() + 1); // unexpected uid
+ assertThrows(SecurityException.class, () -> mInterface.getMaximumDataBlockSize());
+ }
+
+ @Test
+ public void getMaximumDataBlockSize() throws Exception {
+ mPdbService.setAllowedUid(Binder.getCallingUid());
+ assertThat(mInterface.getMaximumDataBlockSize())
+ .isEqualTo(mPdbService.getMaximumFrpDataSize());
+ }
+
+ @Test
+ public void getMaximumDataBlockSizeOfLargerPartition() throws Exception {
+ File dataBlockFile = mTemporaryFolder.newFile();
+ PersistentDataBlockService pdbService = new FakePersistentDataBlockService(mContext,
+ dataBlockFile.getPath(), /* blockDeviceSize */ 128 * 1000);
+ pdbService.setAllowedUid(Binder.getCallingUid());
+ pdbService.formatPartitionLocked(/* setOemUnlockEnabled */ false);
+
+ IPersistentDataBlockService service = pdbService.getInterfaceForTesting();
+ assertThat(service.getMaximumDataBlockSize()).isEqualTo(MAX_DATA_BLOCK_SIZE);
+ }
+
+ @Test
+ public void getFrpDataBlockSizeGrantedByUid() throws Exception {
+ assertThat(mInterface.write(SMALL_DATA)).isEqualTo(SMALL_DATA.length);
+
+ mPdbService.setAllowedUid(Binder.getCallingUid());
+ assertThat(mInterface.getDataBlockSize()).isEqualTo(SMALL_DATA.length);
+
+ // Modify the magic / type marker. In the current implementation, getting the FRP data block
+ // size does not check digest.
+ tamperWithMagic();
+ assertThat(mInterface.getDataBlockSize()).isEqualTo(0);
+ }
+
+ @Test
+ public void getFrpDataBlockSizeGrantedByPermission() throws Exception {
+ assertThat(mInterface.write(SMALL_DATA)).isEqualTo(SMALL_DATA.length);
+
+ mPdbService.setAllowedUid(Binder.getCallingUid() + 1); // unexpected uid
+ grantAccessPdbStatePermission();
+
+ assertThat(mInterface.getDataBlockSize()).isEqualTo(SMALL_DATA.length);
+
+ // Modify the magic / type marker. In the current implementation, getting the FRP data block
+ // size does not check digest.
+ tamperWithMagic();
+ assertThat(mInterface.getDataBlockSize()).isEqualTo(0);
+ }
+
+ @Test
+ public void wipePermissionCheck() throws Exception {
+ denyOemUnlockPermission();
+ assertThrows(SecurityException.class, () -> mInterface.wipe());
+ }
+
+ @Test
+ public void wipeMakesItNotWritable() throws Exception {
+ grantOemUnlockPermission();
+ mInterface.wipe();
+
+ // Verify that nothing is written.
+ final int headerAndDataBytes = 4 + SMALL_DATA.length;
+ assertThat(mInterface.write(SMALL_DATA)).isLessThan(0);
+ assertThat(readBackingFile(DIGEST_SIZE_BYTES + 4, headerAndDataBytes).array())
+ .isEqualTo(new byte[headerAndDataBytes]);
+
+ mInternalInterface.setFrpCredentialHandle(SMALL_DATA);
+ assertThat(readBackingFile(mPdbService.getFrpCredentialDataOffset() + 4,
+ headerAndDataBytes)
+ .array())
+ .isEqualTo(new byte[headerAndDataBytes]);
+
+ mInternalInterface.setTestHarnessModeData(SMALL_DATA);
+ assertThat(readBackingFile(mPdbService.getTestHarnessModeDataOffset() + 4,
+ headerAndDataBytes)
+ .array())
+ .isEqualTo(new byte[headerAndDataBytes]);
+ }
+
+ @Test
+ public void hasFrpCredentialHandleGrantedByUid() throws Exception {
+ mPdbService.setAllowedUid(Binder.getCallingUid());
+
+ assertThat(mInterface.hasFrpCredentialHandle()).isFalse();
+ mInternalInterface.setFrpCredentialHandle(SMALL_DATA);
+ assertThat(mInterface.hasFrpCredentialHandle()).isTrue();
+ }
+
+ @Test
+ public void hasFrpCredentialHandleGrantedByPermission() throws Exception {
+ mPdbService.setAllowedUid(Binder.getCallingUid() + 1); // unexpected uid
+ grantAccessPdbStatePermission();
+
+ assertThat(mInterface.hasFrpCredentialHandle()).isFalse();
+ mInternalInterface.setFrpCredentialHandle(SMALL_DATA);
+ assertThat(mInterface.hasFrpCredentialHandle()).isTrue();
+ }
+
+ @Test
+ public void clearTestHarnessModeData() throws Exception {
+ mInternalInterface.setTestHarnessModeData(SMALL_DATA);
+ mInternalInterface.clearTestHarnessModeData();
+
+ assertThat(readBackingFile(mPdbService.getTestHarnessModeDataOffset(),
+ MAX_TEST_MODE_DATA_SIZE).array())
+ .isEqualTo(new byte[MAX_TEST_MODE_DATA_SIZE]);
+ }
+
+ @Test
+ public void getAllowedUid() throws Exception {
+ assertThat(mInternalInterface.getAllowedUid()).isEqualTo(Binder.getCallingUid());
+ }
+
+ @Test
+ public void oemUnlockWithoutPermission() throws Exception {
+ denyOemUnlockPermission();
+
+ assertThrows(SecurityException.class, () -> mInterface.setOemUnlockEnabled(true));
+ }
+
+ @Test
+ public void oemUnlockNotAdmin() throws Exception {
+ grantOemUnlockPermission();
+ makeUserAdmin(false);
+
+ assertThrows(SecurityException.class, () -> mInterface.setOemUnlockEnabled(true));
+ }
+
+ @Test
+ public void oemUnlock() throws Exception {
+ grantOemUnlockPermission();
+ makeUserAdmin(true);
+
+ mInterface.setOemUnlockEnabled(true);
+ assertThat(mInterface.getOemUnlockEnabled()).isTrue();
+ assertThat(mOemUnlockPropertyValue).isEqualTo("1");
+ }
+
+ @Test
+ public void oemUnlockUserRestriction_OemUnlock() throws Exception {
+ grantOemUnlockPermission();
+ makeUserAdmin(true);
+ when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_OEM_UNLOCK)))
+ .thenReturn(true);
+
+ assertThrows(SecurityException.class, () -> mInterface.setOemUnlockEnabled(true));
+ }
+
+ @Test
+ public void oemUnlockUserRestriction_FactoryReset() throws Exception {
+ grantOemUnlockPermission();
+ makeUserAdmin(true);
+ when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_FACTORY_RESET)))
+ .thenReturn(true);
+
+ assertThrows(SecurityException.class, () -> mInterface.setOemUnlockEnabled(true));
+ }
+
+ @Test
+ public void oemUnlockIgnoreTampering() throws Exception {
+ grantOemUnlockPermission();
+ makeUserAdmin(true);
+
+ // The current implementation does not check digest before set or get the oem unlock bit.
+ tamperWithDigest();
+ mInterface.setOemUnlockEnabled(true);
+ assertThat(mOemUnlockPropertyValue).isEqualTo("1");
+ tamperWithDigest();
+ assertThat(mInterface.getOemUnlockEnabled()).isTrue();
+ }
+
+ @Test
+ public void getOemUnlockEnabledPermissionCheck_NoPermission() throws Exception {
+ assertThrows(SecurityException.class, () -> mInterface.getOemUnlockEnabled());
+ }
+
+ @Test
+ public void getOemUnlockEnabledPermissionCheck_OemUnlcokState() throws Exception {
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mContext)
+ .checkCallingOrSelfPermission(eq(Manifest.permission.OEM_UNLOCK_STATE));
+ assertThat(mInterface.getOemUnlockEnabled()).isFalse();
+ }
+
+ @Test
+ public void getOemUnlockEnabledPermissionCheck_ReadOemUnlcokState() throws Exception {
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mContext)
+ .checkCallingOrSelfPermission(eq(Manifest.permission.READ_OEM_UNLOCK_STATE));
+ assertThat(mInterface.getOemUnlockEnabled()).isFalse();
+ }
+
+ @Test
+ public void forceOemUnlock_RequiresNoPermission() throws Exception {
+ denyOemUnlockPermission();
+
+ mInternalInterface.forceOemUnlockEnabled(true);
+
+ assertThat(mOemUnlockPropertyValue).isEqualTo("1");
+ assertThat(readBackingFile(mPdbService.getOemUnlockDataOffset(), 1).array())
+ .isEqualTo(new byte[] { 1 });
+ }
+
+ @Test
+ public void getFlashLockStatePermissionCheck_NoPermission() throws Exception {
+ assertThrows(SecurityException.class, () -> mInterface.getFlashLockState());
+ }
+
+ @Test
+ public void getFlashLockStatePermissionCheck_OemUnlcokState() throws Exception {
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mContext)
+ .checkCallingOrSelfPermission(eq(Manifest.permission.OEM_UNLOCK_STATE));
+ mInterface.getFlashLockState(); // Do not throw
+ }
+
+ @Test
+ public void getFlashLockStatePermissionCheck_ReadOemUnlcokState() throws Exception {
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mContext)
+ .checkCallingOrSelfPermission(eq(Manifest.permission.READ_OEM_UNLOCK_STATE));
+ mInterface.getFlashLockState(); // Do not throw
+ }
+
+ private void tamperWithDigest() throws Exception {
+ try (var ch = FileChannel.open(mDataBlockFile.toPath(), StandardOpenOption.WRITE)) {
+ ch.write(ByteBuffer.wrap("tampered-digest".getBytes()));
+ }
+ }
+
+ private void tamperWithMagic() throws Exception {
+ try (var ch = FileChannel.open(mDataBlockFile.toPath(), StandardOpenOption.WRITE)) {
+ ch.write(ByteBuffer.wrap("mark".getBytes()), DIGEST_SIZE_BYTES);
+ }
+ }
+
+ private void makeUserAdmin(boolean isAdmin) {
+ when(mUserManager.isUserAdmin(anyInt())).thenReturn(isAdmin);
+ }
+
+ private void grantOemUnlockPermission() {
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mContext)
+ .checkCallingOrSelfPermission(eq(Manifest.permission.OEM_UNLOCK_STATE));
+ doNothing().when(mContext)
+ .enforceCallingOrSelfPermission(eq(Manifest.permission.OEM_UNLOCK_STATE),
+ anyString());
+ }
+
+ private void denyOemUnlockPermission() {
+ doReturn(PackageManager.PERMISSION_DENIED).when(mContext)
+ .checkCallingOrSelfPermission(eq(Manifest.permission.OEM_UNLOCK_STATE));
+ }
+
+ private void grantAccessPdbStatePermission() {
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mContext)
+ .checkCallingPermission(eq(Manifest.permission.ACCESS_PDB_STATE));
+ }
+
+ private ByteBuffer readBackingFile(long position, int size) throws Exception {
+ try (var ch = FileChannel.open(mDataBlockFile.toPath(), StandardOpenOption.READ)) {
+ var buffer = ByteBuffer.allocate(size);
+ assertThat(ch.read(buffer, position)).isGreaterThan(0);
+ return buffer;
+ }
+ }
+}
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
index f61cce6..daaab33 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -156,6 +156,7 @@
method @Deprecated public int getInt(int);
method @Deprecated public long getLong(int);
method @Deprecated public android.net.Uri getNotificationUri();
+ method @Deprecated public java.util.List<android.net.Uri> getNotificationUris();
method @Deprecated public int getPosition();
method @Deprecated public short getShort(int);
method @Deprecated public String getString(int);
@@ -179,6 +180,7 @@
method @Deprecated public android.os.Bundle respond(android.os.Bundle);
method @Deprecated public void setExtras(android.os.Bundle);
method @Deprecated public void setNotificationUri(android.content.ContentResolver, android.net.Uri);
+ method @Deprecated public void setNotificationUris(android.content.ContentResolver, java.util.List<android.net.Uri>);
method @Deprecated public void unregisterContentObserver(android.database.ContentObserver);
method @Deprecated public void unregisterDataSetObserver(android.database.DataSetObserver);
}