Merge "Add more javadocs to SyncFence" into tm-dev
diff --git a/core/api/current.txt b/core/api/current.txt
index 5b1f59a..56415ec 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -16870,6 +16870,7 @@
field public static final long USAGE_SENSOR_DIRECT_DATA = 8388608L; // 0x800000L
field public static final long USAGE_VIDEO_ENCODE = 65536L; // 0x10000L
field public static final int YCBCR_420_888 = 35; // 0x23
+ field public static final int YCBCR_P010 = 54; // 0x36
}
public final class Sensor {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index ed7fc66..2c29343 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -205,7 +205,6 @@
field public static final String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS";
field public static final String MODIFY_QUIET_MODE = "android.permission.MODIFY_QUIET_MODE";
field public static final String MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE = "android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE";
- field public static final String MODIFY_TOUCH_MODE_STATE = "android.permission.MODIFY_TOUCH_MODE_STATE";
field public static final String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
field public static final String NETWORK_AIRPLANE_MODE = "android.permission.NETWORK_AIRPLANE_MODE";
field public static final String NETWORK_CARRIER_PROVISIONING = "android.permission.NETWORK_CARRIER_PROVISIONING";
@@ -6789,7 +6788,8 @@
method @NonNull @RequiresPermission(android.Manifest.permission.TIS_EXTENSION_INTERFACE) public java.util.List<java.lang.String> getAvailableExtensionInterfaceNames(@NonNull String);
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String);
method @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public int getClientPid(@NonNull String);
- method @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public int getClientPriority(int, @Nullable String);
+ method @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public int getClientPriority(int, @NonNull String);
+ method @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public int getClientPriority(int);
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TUNED_INFO) public java.util.List<android.media.tv.TunedInfo> getCurrentTunedInfos();
method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList();
method @Nullable @RequiresPermission(android.Manifest.permission.TIS_EXTENSION_INTERFACE) public android.os.IBinder getExtensionInterface(@NonNull String, @NonNull String);
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index ac1bcf3..1e4c9501 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -63,6 +63,7 @@
D_FP32,
DS_FP32UI8,
S_UI8,
+ YCBCR_P010,
})
public @interface Format {
}
@@ -96,6 +97,14 @@
public static final int DS_FP32UI8 = 0x34;
/** Format: 8 bits stencil */
public static final int S_UI8 = 0x35;
+ /**
+ * <p>Android YUV P010 format.</p>
+ *
+ * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
+ * followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit
+ * little-endian value, with the lower 6 bits set to zero.
+ */
+ public static final int YCBCR_P010 = 0x36;
// Note: do not rename, this field is used by native code
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -422,6 +431,7 @@
case D_FP32:
case DS_FP32UI8:
case S_UI8:
+ case YCBCR_P010:
return true;
}
return false;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 2359d8d..2717463 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2031,14 +2031,20 @@
* @param inputConnection the connection to be invalidated.
* @param textSnapshot {@link TextSnapshot} to be used to update {@link EditorInfo}.
* @param sessionId the session ID to be sent.
+ * @return {@code true} if the operation is done. {@code false} if the caller needs to fall back
+ * to {@link InputMethodManager#restartInput(View)}.
* @hide
*/
- public void doInvalidateInput(@NonNull RemoteInputConnectionImpl inputConnection,
+ public boolean doInvalidateInput(@NonNull RemoteInputConnectionImpl inputConnection,
@NonNull TextSnapshot textSnapshot, int sessionId) {
synchronized (mH) {
if (mServedInputConnection != inputConnection || mCurrentTextBoxAttribute == null) {
// OK to ignore because the calling InputConnection is already abandoned.
- return;
+ return true;
+ }
+ if (mCurrentInputMethodSession == null) {
+ // IME is not yet bound to the client. Need to fall back to the restartInput().
+ return false;
}
final EditorInfo editorInfo = mCurrentTextBoxAttribute.createCopyInternal();
editorInfo.initialSelStart = mCursorSelStart = textSnapshot.getSelectionStart();
@@ -2051,6 +2057,7 @@
sessionId);
forAccessibilitySessions(wrapper -> wrapper.invalidateInput(editorInfo,
mServedInputConnection, sessionId));
+ return true;
}
}
diff --git a/core/java/android/webkit/UserPackage.java b/core/java/android/webkit/UserPackage.java
index 5bcfa8b..1da2af4 100644
--- a/core/java/android/webkit/UserPackage.java
+++ b/core/java/android/webkit/UserPackage.java
@@ -34,7 +34,7 @@
private final UserInfo mUserInfo;
private final PackageInfo mPackageInfo;
- public static final int MINIMUM_SUPPORTED_SDK = Build.VERSION_CODES.S;
+ public static final int MINIMUM_SUPPORTED_SDK = Build.VERSION_CODES.TIRAMISU;
public UserPackage(UserInfo user, PackageInfo packageInfo) {
this.mUserInfo = user;
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index cf6807e..0ef37d1 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -51,7 +51,7 @@
// visible for WebViewZygoteInit to look up the class by reflection and call preloadInZygote.
/** @hide */
private static final String CHROMIUM_WEBVIEW_FACTORY =
- "com.android.webview.chromium.WebViewChromiumFactoryProviderForS";
+ "com.android.webview.chromium.WebViewChromiumFactoryProviderForT";
private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create";
diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
index d1942ac..780de0e 100644
--- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
@@ -282,9 +282,8 @@
if (!alwaysTrueEndBatchEditDetected) {
final TextSnapshot textSnapshot = ic.takeSnapshot();
- if (textSnapshot != null) {
- mParentInputMethodManager.doInvalidateInput(this, textSnapshot,
- nextSessionId);
+ if (textSnapshot != null && mParentInputMethodManager.doInvalidateInput(
+ this, textSnapshot, nextSessionId)) {
return;
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3b2a248..d4c03e4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4718,10 +4718,10 @@
<permission android:name="android.permission.READ_FRAME_BUFFER"
android:protectionLevel="signature|recents" />
- <!-- @SystemApi Allows an application to change the touch mode state.
+ <!-- Allows an application to change the touch mode state.
Without this permission, an app can only change the touch mode
if it currently has focus.
- @hide -->
+ @hide -->
<permission android:name="android.permission.MODIFY_TOUCH_MODE_STATE"
android:protectionLevel="signature" />
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 9feb619..b341a4e 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -428,7 +428,7 @@
/**
* <p>Private raw camera sensor image format, a single channel image with
- * implementation depedent pixel layout.</p>
+ * implementation dependent pixel layout.</p>
*
* <p>RAW_PRIVATE is a format for unprocessed raw image buffers coming from an
* image sensor. The actual structure of buffers of this format is
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index 101295d..11ecc91 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -35,6 +35,9 @@
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.content.ClipDescription;
import android.content.Context;
import android.content.res.Configuration;
@@ -54,6 +57,7 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
+import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -205,6 +209,7 @@
break;
case ACTION_DRAG_ENTERED:
pd.dragLayout.show();
+ pd.dragLayout.update(event);
break;
case ACTION_DRAG_LOCATION:
pd.dragLayout.update(event);
@@ -250,10 +255,6 @@
// Hide the window if another drag hasn't been started while animating the drop
setDropTargetWindowVisibility(pd, View.INVISIBLE);
}
-
- // Clean up the drag surface
- mTransaction.reparent(dragSurface, null);
- mTransaction.apply();
});
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index e8bae0f..7568310 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -123,6 +123,13 @@
}
/**
+ * Returns the number of targets.
+ */
+ int getNumTargets() {
+ return mTargets.size();
+ }
+
+ /**
* Returns the target's regions based on the current state of the device and display.
*/
@NonNull
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index d395f95..25fe8b9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -17,6 +17,7 @@
package com.android.wm.shell.draganddrop;
import static android.app.StatusBarManager.DISABLE_NONE;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -24,6 +25,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.StatusBarManager;
@@ -44,6 +46,7 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
+import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -135,6 +138,12 @@
}
}
+ private void updateContainerMarginsForSingleTask() {
+ mDropZoneView1.setContainerMargin(
+ mDisplayMargin, mDisplayMargin, mDisplayMargin, mDisplayMargin);
+ mDropZoneView2.setContainerMargin(0, 0, 0, 0);
+ }
+
private void updateContainerMargins(int orientation) {
final float halfMargin = mDisplayMargin / 2f;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
@@ -165,11 +174,20 @@
if (!alreadyInSplit) {
ActivityManager.RunningTaskInfo taskInfo1 = mPolicy.getLatestRunningTask();
if (taskInfo1 != null) {
- Drawable icon1 = mIconProvider.getIcon(taskInfo1.topActivityInfo);
- int bgColor1 = getResizingBackgroundColor(taskInfo1);
- mDropZoneView1.setAppInfo(bgColor1, icon1);
- mDropZoneView2.setAppInfo(bgColor1, icon1);
- updateDropZoneSizes(null, null); // passing null splits the views evenly
+ final int activityType = taskInfo1.getActivityType();
+ if (activityType == ACTIVITY_TYPE_STANDARD) {
+ Drawable icon1 = mIconProvider.getIcon(taskInfo1.topActivityInfo);
+ int bgColor1 = getResizingBackgroundColor(taskInfo1);
+ mDropZoneView1.setAppInfo(bgColor1, icon1);
+ mDropZoneView2.setAppInfo(bgColor1, icon1);
+ updateDropZoneSizes(null, null); // passing null splits the views evenly
+ } else {
+ // We use the first drop zone to show the fullscreen highlight, and don't need
+ // to set additional info
+ mDropZoneView1.setForceIgnoreBottomMargin(true);
+ updateDropZoneSizesForSingleTask();
+ updateContainerMarginsForSingleTask();
+ }
}
} else {
// We're already in split so get taskInfo from the controller to populate icon / color.
@@ -195,6 +213,21 @@
}
}
+ private void updateDropZoneSizesForSingleTask() {
+ final LinearLayout.LayoutParams dropZoneView1 =
+ (LayoutParams) mDropZoneView1.getLayoutParams();
+ final LinearLayout.LayoutParams dropZoneView2 =
+ (LayoutParams) mDropZoneView2.getLayoutParams();
+ dropZoneView1.width = MATCH_PARENT;
+ dropZoneView1.height = MATCH_PARENT;
+ dropZoneView2.width = 0;
+ dropZoneView2.height = 0;
+ dropZoneView1.weight = 1;
+ dropZoneView2.weight = 0;
+ mDropZoneView1.setLayoutParams(dropZoneView1);
+ mDropZoneView2.setLayoutParams(dropZoneView2);
+ }
+
/**
* Sets the size of the two drop zones based on the provided bounds. The divider sits between
* the views and its size is included in the calculations.
@@ -265,9 +298,12 @@
// Animating to no target
animateSplitContainers(false, null /* animCompleteCallback */);
} else if (mCurrentTarget == null) {
- // Animating to first target
- animateSplitContainers(true, null /* animCompleteCallback */);
- animateHighlight(target);
+ if (mPolicy.getNumTargets() == 1) {
+ animateFullscreenContainer(true);
+ } else {
+ animateSplitContainers(true, null /* animCompleteCallback */);
+ animateHighlight(target);
+ }
} else {
// Switching between targets
mDropZoneView1.animateSwitch();
@@ -283,6 +319,10 @@
public void hide(DragEvent event, Runnable hideCompleteCallback) {
mIsShowing = false;
animateSplitContainers(false, hideCompleteCallback);
+ // Reset the state if we previously force-ignore the bottom margin
+ mDropZoneView1.setForceIgnoreBottomMargin(false);
+ mDropZoneView2.setForceIgnoreBottomMargin(false);
+ updateContainerMargins(getResources().getConfiguration().orientation);
mCurrentTarget = null;
}
@@ -297,11 +337,63 @@
// Process the drop
mPolicy.handleDrop(mCurrentTarget, event.getClipData());
- // TODO(b/169894807): Coordinate with dragSurface
+ // Start animating the drop UI out with the drag surface
hide(event, dropCompleteCallback);
+ hideDragSurface(dragSurface);
return handledDrop;
}
+ private void hideDragSurface(SurfaceControl dragSurface) {
+ final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
+ final ValueAnimator dragSurfaceAnimator = ValueAnimator.ofFloat(0f, 1f);
+ // Currently the splash icon animation runs with the default ValueAnimator duration of
+ // 300ms
+ dragSurfaceAnimator.setDuration(300);
+ dragSurfaceAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ dragSurfaceAnimator.addUpdateListener(animation -> {
+ float t = animation.getAnimatedFraction();
+ float alpha = 1f - t;
+ // TODO: Scale the drag surface as well once we make all the source surfaces
+ // consistent
+ tx.setAlpha(dragSurface, alpha);
+ tx.apply();
+ });
+ dragSurfaceAnimator.addListener(new AnimatorListenerAdapter() {
+ private boolean mCanceled = false;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ cleanUpSurface();
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mCanceled) {
+ // Already handled above
+ return;
+ }
+ cleanUpSurface();
+ }
+
+ private void cleanUpSurface() {
+ // Clean up the drag surface
+ tx.remove(dragSurface);
+ tx.apply();
+ }
+ });
+ dragSurfaceAnimator.start();
+ }
+
+ private void animateFullscreenContainer(boolean visible) {
+ mStatusBarManager.disable(visible
+ ? HIDE_STATUS_BAR_FLAGS
+ : DISABLE_NONE);
+ // We're only using the first drop zone if there is one fullscreen target
+ mDropZoneView1.setShowingMargin(visible);
+ mDropZoneView1.setShowingHighlight(visible);
+ }
+
private void animateSplitContainers(boolean visible, Runnable animCompleteCallback) {
mStatusBarManager.disable(visible
? HIDE_STATUS_BAR_FLAGS
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java
index a3ee8ae..38870bc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java
@@ -65,6 +65,7 @@
private final float[] mContainerMargin = new float[4];
private float mCornerRadius;
private float mBottomInset;
+ private boolean mIgnoreBottomMargin;
private int mMarginColor; // i.e. color used for negative space like the container insets
private boolean mShowingHighlight;
@@ -141,6 +142,14 @@
}
}
+ /** Ignores the bottom margin provided by the insets. */
+ public void setForceIgnoreBottomMargin(boolean ignoreBottomMargin) {
+ mIgnoreBottomMargin = ignoreBottomMargin;
+ if (mMarginPercent > 0) {
+ mMarginView.invalidate();
+ }
+ }
+
/** Sets the bottom inset so the drop zones are above bottom navigation. */
public void setBottomInset(float bottom) {
mBottomInset = bottom;
@@ -257,7 +266,8 @@
mPath.addRoundRect(mContainerMargin[0] * mMarginPercent,
mContainerMargin[1] * mMarginPercent,
getWidth() - (mContainerMargin[2] * mMarginPercent),
- getHeight() - (mContainerMargin[3] * mMarginPercent) - mBottomInset,
+ getHeight() - (mContainerMargin[3] * mMarginPercent)
+ - (mIgnoreBottomMargin ? 0 : mBottomInset),
mCornerRadius * mMarginPercent,
mCornerRadius * mMarginPercent,
Path.Direction.CW);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 96809bd..69fe5ee 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1863,12 +1863,9 @@
* Returns a priority for the given use case type and the client's foreground or background
* status.
*
- * @param useCase the use case type of the client. When the given use case type is invalid,
- * the default use case type will be used. {@see TvInputService#PriorityHintUseCaseType}.
- * @param sessionId the unique id of the session owned by the client. When {@code null},
- * the caller will be used as a client. When the session is invalid, background status
- * will be used as a client's status. Otherwise, TV app corresponding to the given
- * session id will be used as a client.
+ * @param useCase the use case type of the client.
+ * {@see TvInputService#PriorityHintUseCaseType}.
+ * @param sessionId the unique id of the session owned by the client.
* {@see TvInputService#onCreateSession(String, String)}.
*
* @return the use case priority value for the given use case type and the client's foreground
@@ -1879,11 +1876,35 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.TUNER_RESOURCE_ACCESS)
public int getClientPriority(@TvInputService.PriorityHintUseCaseType int useCase,
- @Nullable String sessionId) {
+ @NonNull String sessionId) {
+ Preconditions.checkNotNull(sessionId);
+ if (!isValidUseCase(useCase)) {
+ throw new IllegalArgumentException("Invalid use case: " + useCase);
+ }
return getClientPriorityInternal(useCase, sessionId);
};
/**
+ * Returns a priority for the given use case type and the caller's foreground or background
+ * status.
+ *
+ * @param useCase the use case type of the caller.
+ * {@see TvInputService#PriorityHintUseCaseType}.
+ *
+ * @return the use case priority value for the given use case type and the caller's foreground
+ * or background status.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.TUNER_RESOURCE_ACCESS)
+ public int getClientPriority(@TvInputService.PriorityHintUseCaseType int useCase) {
+ if (!isValidUseCase(useCase)) {
+ throw new IllegalArgumentException("Invalid use case: " + useCase);
+ }
+ return getClientPriorityInternal(useCase, null);
+ };
+ /**
* Creates a recording {@link Session} for a given TV input.
*
* <p>The number of sessions that can be created at the same time is limited by the capability
@@ -1935,6 +1956,14 @@
}
}
+ private boolean isValidUseCase(int useCase) {
+ return useCase == TvInputService.PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND
+ || useCase == TvInputService.PRIORITY_HINT_USE_CASE_TYPE_SCAN
+ || useCase == TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK
+ || useCase == TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE
+ || useCase == TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD;
+ }
+
/**
* Returns the TvStreamConfig list of the given TV input.
*
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index d0acc53..397c704 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -1839,7 +1839,7 @@
if (mDemuxClient == nullptr) {
return nullptr;
}
- long time = mDemuxClient->getAvSyncTime((int)id);
+ int64_t time = mDemuxClient->getAvSyncTime((int)id);
if (time >= 0) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass longClazz = env->FindClass("java/lang/Long");
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3f80647..23b2529 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2407,4 +2407,7 @@
<string name="add_user_supervised" translatable="false">@*android:string/supervised_user_creation_label</string>
<!-- Manage users - For system user management [CHAR LIMIT=40] -->
<string name="manage_users">Manage users</string>
+
+ <!-- Toast shown when a notification does not support dragging to split [CHAR LIMIT=NONE] -->
+ <string name="drag_split_not_supported">This notification does not support dragging to Splitscreen.</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
index 06b739b..c2c40d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
@@ -17,6 +17,11 @@
package com.android.systemui.statusbar.notification.row;
+import static android.widget.Toast.LENGTH_SHORT;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.app.Notification;
import android.app.PendingIntent;
@@ -33,13 +38,15 @@
import android.util.Log;
import android.view.DragEvent;
import android.view.HapticFeedbackConstants;
+import android.view.SurfaceControl;
import android.view.View;
import android.widget.ImageView;
+import android.widget.Toast;
import androidx.annotation.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -55,12 +62,15 @@
private final Context mContext;
private final HeadsUpManager mHeadsUpManager;
+ private final ShadeController mShadeController;
@Inject
public ExpandableNotificationRowDragController(Context context,
- HeadsUpManager headsUpManager) {
+ HeadsUpManager headsUpManager,
+ ShadeController shadeController) {
mContext = context;
mHeadsUpManager = headsUpManager;
+ mShadeController = shadeController;
init();
}
@@ -87,6 +97,16 @@
final PendingIntent contentIntent = notification.contentIntent != null
? notification.contentIntent
: notification.fullScreenIntent;
+ if (contentIntent == null) {
+ if (!enr.isPinned()) {
+ // We dismiss the shade for consistency, but also because toasts currently don't
+ // show above the shade
+ dismissShade();
+ }
+ Toast.makeText(mContext, R.string.drag_split_not_supported, LENGTH_SHORT)
+ .show();
+ return;
+ }
Bitmap iconBitmap = getBitmapFromDrawable(
getPkgIcon(enr.getEntry().getSbn().getPackageName()));
@@ -97,15 +117,30 @@
ClipDescription clipDescription = new ClipDescription("Drag And Drop",
new String[]{ClipDescription.MIMETYPE_APPLICATION_ACTIVITY});
Intent dragIntent = new Intent();
- dragIntent.putExtra("android.intent.extra.PENDING_INTENT", contentIntent);
+ dragIntent.putExtra(ClipDescription.EXTRA_PENDING_INTENT, contentIntent);
dragIntent.putExtra(Intent.EXTRA_USER, android.os.Process.myUserHandle());
ClipData.Item item = new ClipData.Item(dragIntent);
ClipData dragData = new ClipData(clipDescription, item);
View.DragShadowBuilder myShadow = new View.DragShadowBuilder(snapshot);
view.setOnDragListener(getDraggedViewDragListener());
- view.startDragAndDrop(dragData, myShadow, null, View.DRAG_FLAG_GLOBAL);
+ boolean result = view.startDragAndDrop(dragData, myShadow, null, View.DRAG_FLAG_GLOBAL
+ | View.DRAG_FLAG_REQUEST_SURFACE_FOR_RETURN_ANIMATION);
+ if (result) {
+ view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ if (enr.isPinned()) {
+ mHeadsUpManager.releaseAllImmediately();
+ } else {
+ dismissShade();
+ }
+ }
}
+ private void dismissShade() {
+ // Speed up dismissing the shade since the drag needs to be handled by
+ // the shell layer underneath
+ mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
+ false /* delayed */, 1.1f /* speedUpFactor */);
+ }
private Drawable getPkgIcon(String pkgName) {
Drawable pkgicon = null;
@@ -145,16 +180,6 @@
return (view, dragEvent) -> {
switch (dragEvent.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
- view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- if (view instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow enr = (ExpandableNotificationRow) view;
- if (enr.isPinned()) {
- mHeadsUpManager.releaseAllImmediately();
- } else {
- Dependency.get(ShadeController.class).animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
- }
- }
return true;
case DragEvent.ACTION_DRAG_ENDED:
if (dragEvent.getResult()) {
@@ -162,10 +187,55 @@
ExpandableNotificationRow enr = (ExpandableNotificationRow) view;
enr.dragAndDropSuccess();
}
+ } else {
+ // Fade out the drag surface in place instead of animating back to the
+ // start position now that the shade is closed
+ fadeOutAndRemoveDragSurface(dragEvent);
}
+ // Clear the drag listener set above
+ view.setOnDragListener(null);
return true;
}
return false;
};
}
+
+ private void fadeOutAndRemoveDragSurface(DragEvent dragEvent) {
+ SurfaceControl dragSurface = dragEvent.getDragSurface();
+ SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
+ ValueAnimator returnAnimator = ValueAnimator.ofFloat(0f, 1f);
+ returnAnimator.setDuration(200);
+ returnAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ returnAnimator.addUpdateListener(animation -> {
+ float t = animation.getAnimatedFraction();
+ float alpha = 1f - t;
+ tx.setAlpha(dragSurface, alpha);
+ tx.apply();
+ });
+ returnAnimator.addListener(new AnimatorListenerAdapter() {
+ private boolean mCanceled = false;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ cleanUpSurface();
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mCanceled) {
+ // Already handled above
+ return;
+ }
+ cleanUpSurface();
+ }
+
+ private void cleanUpSurface() {
+ tx.remove(dragSurface);
+ tx.apply();
+ tx.close();
+ }
+ });
+ returnAnimator.start();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
index 24a0ad3..bc54bf8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
@@ -18,6 +18,8 @@
import static android.view.DragEvent.ACTION_DRAG_STARTED;
+import android.app.Notification;
+import android.app.PendingIntent;
import android.content.Context;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -36,7 +38,12 @@
import org.junit.runner.RunWith;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -58,6 +65,7 @@
private NotificationMenuRow mMenuRow = mock(NotificationMenuRow.class);
private NotificationMenuRowPlugin.MenuItem mMenuItem =
mock(NotificationMenuRowPlugin.MenuItem.class);
+ private ShadeController mShadeController = mock(ShadeController.class);
@Before
public void setUp() throws Exception {
@@ -69,11 +77,15 @@
mContext,
mDependency,
TestableLooper.get(this));
- mRow = mNotificationTestHelper.createRow();
+ mRow = spy(mNotificationTestHelper.createRow());
+ Notification notification = mRow.getEntry().getSbn().getNotification();
+ notification.contentIntent = mock(PendingIntent.class);
+ doReturn(true).when(mRow).startDragAndDrop(any(), any(), any(), anyInt());
mGroupRow = mNotificationTestHelper.createGroup(4);
when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem);
- mController = new ExpandableNotificationRowDragController(mContext, mHeadsUpManager);
+ mController = new ExpandableNotificationRowDragController(mContext, mHeadsUpManager,
+ mShadeController);
}
@Test
@@ -86,10 +98,6 @@
mRow.doLongClickCallback(0, 0);
mRow.doDragCallback(0, 0);
verify(controller).startDragAndDrop(mRow);
-
- // Simulate the drag start
- mRow.dispatchDragEvent(DragEvent.obtain(ACTION_DRAG_STARTED, 0, 0, 0, 0, null, null, null,
- null, null, false));
verify(mHeadsUpManager, times(1)).releaseAllImmediately();
}
@@ -98,14 +106,27 @@
ExpandableNotificationRowDragController controller = createSpyController();
mRow.setDragController(controller);
- mDependency.get(ShadeController.class).instantExpandNotificationsPanel();
+ mRow.doDragCallback(0, 0);
+ verify(controller).startDragAndDrop(mRow);
+ verify(mShadeController).animateCollapsePanels(eq(0), eq(true),
+ eq(false), anyFloat());
+ }
+
+ @Test
+ public void testDoStartDrag_noLaunchIntent() throws Exception {
+ ExpandableNotificationRowDragController controller = createSpyController();
+ mRow.setDragController(controller);
+
+ // Clear the intents
+ Notification notification = mRow.getEntry().getSbn().getNotification();
+ notification.contentIntent = null;
+ notification.fullScreenIntent = null;
+
mRow.doDragCallback(0, 0);
verify(controller).startDragAndDrop(mRow);
- // Simulate the drag start
- mRow.dispatchDragEvent(DragEvent.obtain(ACTION_DRAG_STARTED, 0, 0, 0, 0, null, null, null,
- null, null, false));
- verify(mDependency.get(ShadeController.class)).animateCollapsePanels(0, true);
+ // Verify that we never start the actual drag since there is no content
+ verify(mRow, never()).startDragAndDrop(any(), any(), any(), anyInt());
}
private ExpandableNotificationRowDragController createSpyController() {
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 09ef03c..111bd34 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -67,7 +67,7 @@
*
* @hide Only for use within the system server.
*/
-public abstract class PackageManagerInternal implements PackageSettingsSnapshotProvider {
+public abstract class PackageManagerInternal {
@IntDef(prefix = "PACKAGE_", value = {
PACKAGE_SYSTEM,
PACKAGE_SETUP_WIZARD,
diff --git a/services/core/java/android/content/pm/PackageSettingsSnapshotProvider.java b/services/core/java/android/content/pm/PackageSettingsSnapshotProvider.java
deleted file mode 100644
index 221f172..0000000
--- a/services/core/java/android/content/pm/PackageSettingsSnapshotProvider.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.annotation.NonNull;
-
-import com.android.internal.util.FunctionalUtils;
-import com.android.server.pm.PackageManagerService;
-import com.android.server.pm.PackageSetting;
-import com.android.server.pm.pkg.PackageStateInternal;
-
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-/** @hide */
-public interface PackageSettingsSnapshotProvider {
-
- /**
- * Run a function block that requires access to {@link PackageStateInternal} data. This will
- * ensure the {@link PackageManagerService} lock is taken before any caller's internal lock
- * to avoid deadlock. Note that this method may or may not lock. If a snapshot is available
- * and valid, it will iterate the snapshot set of data.
- */
- void withPackageSettingsSnapshot(
- @NonNull Consumer<Function<String, PackageStateInternal>> block);
-
- /**
- * Variant which returns a value to the caller.
- * @see #withPackageSettingsSnapshot(Consumer)
- */
- <Output> Output withPackageSettingsSnapshotReturning(
- @NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageStateInternal>,
- Output> block);
-
- /**
- * Variant which throws.
- * @see #withPackageSettingsSnapshot(Consumer)
- */
- <ExceptionType extends Exception> void withPackageSettingsSnapshotThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedConsumer<Function<String, PackageStateInternal>,
- ExceptionType> block) throws ExceptionType;
-
- /**
- * Variant which throws 2 exceptions.
- * @see #withPackageSettingsSnapshot(Consumer)
- */
- <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
- withPackageSettingsSnapshotThrowing2(
- @NonNull FunctionalUtils.ThrowingChecked2Consumer<
- Function<String, PackageStateInternal>,
- ExceptionOne, ExceptionTwo> block)
- throws ExceptionOne, ExceptionTwo;
-
- /**
- * Variant which returns a value to the caller and throws.
- * @see #withPackageSettingsSnapshot(Consumer)
- */
- <Output, ExceptionType extends Exception> Output
- withPackageSettingsSnapshotReturningThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedFunction<
- Function<String, PackageStateInternal>, Output, ExceptionType> block)
- throws ExceptionType;
-}
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 9ba9d78..b813bc4 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -159,7 +159,7 @@
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_GAME_SERVICE)) {
mGameServiceController = new GameServiceController(
- BackgroundThread.getExecutor(),
+ context, BackgroundThread.getExecutor(),
new GameServiceProviderSelectorImpl(
context.getResources(),
context.getPackageManager()),
@@ -376,9 +376,10 @@
/**
* Called by games to communicate the current state to the platform.
+ *
* @param packageName The client package name.
- * @param gameState An object set to the current state.
- * @param userId The user associated with this state.
+ * @param gameState An object set to the current state.
+ * @param userId The user associated with this state.
*/
public void setGameState(String packageName, @NonNull GameState gameState,
@UserIdInt int userId) {
@@ -1373,7 +1374,7 @@
* @hide
*/
@VisibleForTesting
- void updateConfigsForUser(@UserIdInt int userId, String ...packageNames) {
+ void updateConfigsForUser(@UserIdInt int userId, String... packageNames) {
try {
synchronized (mDeviceConfigLock) {
for (final String packageName : packageNames) {
@@ -1442,7 +1443,7 @@
final List<PackageInfo> packages =
mPackageManager.getInstalledPackagesAsUser(0, userId);
return packages.stream().filter(e -> e.applicationInfo != null && e.applicationInfo.category
- == ApplicationInfo.CATEGORY_GAME)
+ == ApplicationInfo.CATEGORY_GAME)
.map(e -> e.packageName)
.toArray(String[]::new);
}
diff --git a/services/core/java/com/android/server/app/GameServiceConfiguration.java b/services/core/java/com/android/server/app/GameServiceConfiguration.java
new file mode 100644
index 0000000..1f31a87
--- /dev/null
+++ b/services/core/java/com/android/server/app/GameServiceConfiguration.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2021 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.app;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.UserHandle;
+import android.text.TextUtils;
+
+import java.util.Objects;
+
+/**
+ * Representation of a {@link android.service.games.GameService} provider configuration.
+ */
+final class GameServiceConfiguration {
+ private final String mPackageName;
+ @Nullable
+ private final GameServiceComponentConfiguration mGameServiceComponentConfiguration;
+
+ GameServiceConfiguration(
+ @NonNull String packageName,
+ @Nullable GameServiceComponentConfiguration gameServiceComponentConfiguration) {
+ Objects.requireNonNull(packageName);
+
+ mPackageName = packageName;
+ mGameServiceComponentConfiguration = gameServiceComponentConfiguration;
+ }
+
+ @NonNull
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ @Nullable
+ public GameServiceComponentConfiguration getGameServiceComponentConfiguration() {
+ return mGameServiceComponentConfiguration;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof GameServiceConfiguration)) {
+ return false;
+ }
+
+ GameServiceConfiguration that = (GameServiceConfiguration) o;
+ return TextUtils.equals(mPackageName, that.mPackageName)
+ && Objects.equals(mGameServiceComponentConfiguration,
+ that.mGameServiceComponentConfiguration);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPackageName, mGameServiceComponentConfiguration);
+ }
+
+ @Override
+ public String toString() {
+ return "GameServiceConfiguration{"
+ + "packageName="
+ + mPackageName
+ + ", gameServiceComponentConfiguration="
+ + mGameServiceComponentConfiguration
+ + '}';
+ }
+
+ static final class GameServiceComponentConfiguration {
+ private final UserHandle mUserHandle;
+ private final ComponentName mGameServiceComponentName;
+ private final ComponentName mGameSessionServiceComponentName;
+
+ GameServiceComponentConfiguration(
+ @NonNull UserHandle userHandle, @NonNull ComponentName gameServiceComponentName,
+ @NonNull ComponentName gameSessionServiceComponentName) {
+ Objects.requireNonNull(userHandle);
+ Objects.requireNonNull(gameServiceComponentName);
+ Objects.requireNonNull(gameSessionServiceComponentName);
+
+ mUserHandle = userHandle;
+ mGameServiceComponentName = gameServiceComponentName;
+ mGameSessionServiceComponentName = gameSessionServiceComponentName;
+ }
+
+ @NonNull
+ public UserHandle getUserHandle() {
+ return mUserHandle;
+ }
+
+ @NonNull
+ public ComponentName getGameServiceComponentName() {
+ return mGameServiceComponentName;
+ }
+
+ @NonNull
+ public ComponentName getGameSessionServiceComponentName() {
+ return mGameSessionServiceComponentName;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof GameServiceComponentConfiguration)) {
+ return false;
+ }
+
+ GameServiceComponentConfiguration that =
+ (GameServiceComponentConfiguration) o;
+ return mUserHandle.equals(that.mUserHandle) && mGameServiceComponentName.equals(
+ that.mGameServiceComponentName)
+ && mGameSessionServiceComponentName.equals(
+ that.mGameSessionServiceComponentName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUserHandle,
+ mGameServiceComponentName,
+ mGameSessionServiceComponentName);
+ }
+
+ @Override
+ public String toString() {
+ return "GameServiceComponentConfiguration{"
+ + "userHandle="
+ + mUserHandle
+ + ", gameServiceComponentName="
+ + mGameServiceComponentName
+ + ", gameSessionServiceComponentName="
+ + mGameSessionServiceComponentName
+ + "}";
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/app/GameServiceController.java b/services/core/java/com/android/server/app/GameServiceController.java
index 397439a..db1ca97 100644
--- a/services/core/java/com/android/server/app/GameServiceController.java
+++ b/services/core/java/com/android/server/app/GameServiceController.java
@@ -19,10 +19,17 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.PatternMatcher;
+import android.text.TextUtils;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
+import com.android.server.app.GameServiceConfiguration.GameServiceComponentConfiguration;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -36,8 +43,8 @@
final class GameServiceController {
private static final String TAG = "GameServiceController";
-
private final Object mLock = new Object();
+ private final Context mContext;
private final Executor mBackgroundExecutor;
private final GameServiceProviderSelector mGameServiceProviderSelector;
private final GameServiceProviderInstanceFactory mGameServiceProviderInstanceFactory;
@@ -46,18 +53,24 @@
@Nullable
private volatile String mGameServiceProviderOverride;
@Nullable
+ private BroadcastReceiver mGameServicePackageChangedReceiver;
+ @Nullable
private volatile SystemService.TargetUser mCurrentForegroundUser;
@GuardedBy("mLock")
@Nullable
- private volatile GameServiceProviderConfiguration mActiveGameServiceProviderConfiguration;
+ private volatile GameServiceComponentConfiguration mActiveGameServiceComponentConfiguration;
@GuardedBy("mLock")
@Nullable
private volatile GameServiceProviderInstance mGameServiceProviderInstance;
+ @GuardedBy("mLock")
+ @Nullable
+ private volatile String mActiveGameServiceProviderPackage;
GameServiceController(
- @NonNull Executor backgroundExecutor,
+ @NonNull Context context, @NonNull Executor backgroundExecutor,
@NonNull GameServiceProviderSelector gameServiceProviderSelector,
@NonNull GameServiceProviderInstanceFactory gameServiceProviderInstanceFactory) {
+ mContext = context;
mGameServiceProviderInstanceFactory = gameServiceProviderInstanceFactory;
mBackgroundExecutor = backgroundExecutor;
mGameServiceProviderSelector = gameServiceProviderSelector;
@@ -139,35 +152,92 @@
}
synchronized (mLock) {
- GameServiceProviderConfiguration selectedGameServiceProviderConfiguration =
+ final GameServiceConfiguration selectedGameServiceConfiguration =
mGameServiceProviderSelector.get(mCurrentForegroundUser,
mGameServiceProviderOverride);
+ final String gameServicePackage =
+ selectedGameServiceConfiguration == null ? null :
+ selectedGameServiceConfiguration.getPackageName();
+ final GameServiceComponentConfiguration gameServiceComponentConfiguration =
+ selectedGameServiceConfiguration == null ? null
+ : selectedGameServiceConfiguration
+ .getGameServiceComponentConfiguration();
- boolean didActiveGameServiceProviderChanged =
- !Objects.equals(selectedGameServiceProviderConfiguration,
- mActiveGameServiceProviderConfiguration);
- if (!didActiveGameServiceProviderChanged) {
+ evaluateGameServiceProviderPackageChangedListenerLocked(gameServicePackage);
+
+ boolean didActiveGameServiceProviderChange =
+ !Objects.equals(gameServiceComponentConfiguration,
+ mActiveGameServiceComponentConfiguration);
+ if (!didActiveGameServiceProviderChange) {
return;
}
if (mGameServiceProviderInstance != null) {
Slog.i(TAG, "Stopping Game Service provider: "
- + mActiveGameServiceProviderConfiguration);
+ + mActiveGameServiceComponentConfiguration);
mGameServiceProviderInstance.stop();
+ mGameServiceProviderInstance = null;
}
- mActiveGameServiceProviderConfiguration = selectedGameServiceProviderConfiguration;
-
- if (mActiveGameServiceProviderConfiguration == null) {
+ mActiveGameServiceComponentConfiguration = gameServiceComponentConfiguration;
+ if (mActiveGameServiceComponentConfiguration == null) {
return;
}
Slog.i(TAG,
- "Starting Game Service provider: " + mActiveGameServiceProviderConfiguration);
+ "Starting Game Service provider: " + mActiveGameServiceComponentConfiguration);
mGameServiceProviderInstance =
mGameServiceProviderInstanceFactory.create(
- mActiveGameServiceProviderConfiguration);
+ mActiveGameServiceComponentConfiguration);
mGameServiceProviderInstance.start();
}
}
+
+ @GuardedBy("mLock")
+ private void evaluateGameServiceProviderPackageChangedListenerLocked(
+ @Nullable String gameServicePackage) {
+ if (TextUtils.equals(mActiveGameServiceProviderPackage, gameServicePackage)) {
+ return;
+ }
+
+ if (mGameServicePackageChangedReceiver != null) {
+ mContext.unregisterReceiver(mGameServicePackageChangedReceiver);
+ mGameServicePackageChangedReceiver = null;
+ }
+
+ mActiveGameServiceProviderPackage = gameServicePackage;
+
+ if (TextUtils.isEmpty(mActiveGameServiceProviderPackage)) {
+ return;
+ }
+
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ intentFilter.addDataScheme("package");
+ intentFilter.addDataSchemeSpecificPart(gameServicePackage, PatternMatcher.PATTERN_LITERAL);
+ mGameServicePackageChangedReceiver = new PackageChangedBroadcastReceiver(
+ gameServicePackage);
+ mContext.registerReceiver(
+ mGameServicePackageChangedReceiver,
+ intentFilter);
+ }
+
+ private final class PackageChangedBroadcastReceiver extends BroadcastReceiver {
+ private final String mPackageName;
+
+ PackageChangedBroadcastReceiver(String packageName) {
+ mPackageName = packageName;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!TextUtils.equals(intent.getData().getSchemeSpecificPart(), mPackageName)) {
+ return;
+ }
+ mBackgroundExecutor.execute(
+ GameServiceController.this::evaluateActiveGameServiceProvider);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/app/GameServiceProviderConfiguration.java b/services/core/java/com/android/server/app/GameServiceProviderConfiguration.java
deleted file mode 100644
index 7c8f251..0000000
--- a/services/core/java/com/android/server/app/GameServiceProviderConfiguration.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2021 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.app;
-
-import android.annotation.NonNull;
-import android.content.ComponentName;
-import android.os.UserHandle;
-
-import java.util.Objects;
-
-/**
- * Representation of a {@link android.service.games.GameService} provider configuration.
- */
-final class GameServiceProviderConfiguration {
- private final UserHandle mUserHandle;
- private final ComponentName mGameServiceComponentName;
- private final ComponentName mGameSessionServiceComponentName;
-
- GameServiceProviderConfiguration(
- @NonNull UserHandle userHandle,
- @NonNull ComponentName gameServiceComponentName,
- @NonNull ComponentName gameSessionServiceComponentName) {
- Objects.requireNonNull(userHandle);
- Objects.requireNonNull(gameServiceComponentName);
- Objects.requireNonNull(gameSessionServiceComponentName);
-
- this.mUserHandle = userHandle;
- this.mGameServiceComponentName = gameServiceComponentName;
- this.mGameSessionServiceComponentName = gameSessionServiceComponentName;
- }
-
- @NonNull
- public UserHandle getUserHandle() {
- return mUserHandle;
- }
-
- @NonNull
- public ComponentName getGameServiceComponentName() {
- return mGameServiceComponentName;
- }
-
- @NonNull
- public ComponentName getGameSessionServiceComponentName() {
- return mGameSessionServiceComponentName;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (!(o instanceof GameServiceProviderConfiguration)) {
- return false;
- }
-
- GameServiceProviderConfiguration that = (GameServiceProviderConfiguration) o;
- return mUserHandle.equals(that.mUserHandle)
- && mGameServiceComponentName.equals(that.mGameServiceComponentName)
- && mGameSessionServiceComponentName.equals(that.mGameSessionServiceComponentName);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mUserHandle, mGameServiceComponentName,
- mGameSessionServiceComponentName);
- }
-
- @Override
- public String toString() {
- return "GameServiceProviderConfiguration{"
- + "mUserHandle="
- + mUserHandle
- + ", gameServiceComponentName="
- + mGameServiceComponentName
- + ", gameSessionServiceComponentName="
- + mGameSessionServiceComponentName
- + '}';
- }
-}
diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceFactory.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceFactory.java
index 7640cc5..7dfaec0 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderInstanceFactory.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceFactory.java
@@ -18,12 +18,13 @@
import android.annotation.NonNull;
+import com.android.server.app.GameServiceConfiguration.GameServiceComponentConfiguration;
+
/**
* Factory for creating {@link GameServiceProviderInstance}.
*/
interface GameServiceProviderInstanceFactory {
@NonNull
- GameServiceProviderInstance create(@NonNull
- GameServiceProviderConfiguration gameServiceProviderConfiguration);
+ GameServiceProviderInstance create(@NonNull GameServiceComponentConfiguration configuration);
}
diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java
index 73278e4..0abab6a 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java
@@ -30,6 +30,7 @@
import com.android.internal.infra.ServiceConnector;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
+import com.android.server.app.GameServiceConfiguration.GameServiceComponentConfiguration;
import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerService;
@@ -43,9 +44,9 @@
@NonNull
@Override
public GameServiceProviderInstance create(
- @NonNull GameServiceProviderConfiguration gameServiceProviderConfiguration) {
+ @NonNull GameServiceComponentConfiguration configuration) {
return new GameServiceProviderInstanceImpl(
- gameServiceProviderConfiguration.getUserHandle(),
+ configuration.getUserHandle(),
BackgroundThread.getExecutor(),
mContext,
new GameClassifierImpl(mContext.getPackageManager()),
@@ -53,8 +54,8 @@
ActivityTaskManager.getService(),
(WindowManagerService) ServiceManager.getService(Context.WINDOW_SERVICE),
LocalServices.getService(WindowManagerInternal.class),
- new GameServiceConnector(mContext, gameServiceProviderConfiguration),
- new GameSessionServiceConnector(mContext, gameServiceProviderConfiguration));
+ new GameServiceConnector(mContext, configuration),
+ new GameSessionServiceConnector(mContext, configuration));
}
private static final class GameServiceConnector extends ServiceConnector.Impl<IGameService> {
@@ -63,7 +64,7 @@
GameServiceConnector(
@NonNull Context context,
- @NonNull GameServiceProviderConfiguration configuration) {
+ @NonNull GameServiceComponentConfiguration configuration) {
super(context, new Intent(GameService.ACTION_GAME_SERVICE)
.setComponent(configuration.getGameServiceComponentName()),
BINDING_FLAGS, configuration.getUserHandle().getIdentifier(),
@@ -86,7 +87,7 @@
GameSessionServiceConnector(
@NonNull Context context,
- @NonNull GameServiceProviderConfiguration configuration) {
+ @NonNull GameServiceComponentConfiguration configuration) {
super(context, new Intent(GameSessionService.ACTION_GAME_SESSION_SERVICE)
.setComponent(configuration.getGameSessionServiceComponentName()),
BINDING_FLAGS, configuration.getUserHandle().getIdentifier(),
diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
index 4eba771..e8d9dad 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
@@ -244,11 +244,11 @@
// TODO(b/204503192): It is possible that the game service is disconnected. In this
// case we should avoid rebinding just to shut it down again.
- AndroidFuture<Void> unusedPostDisconnectedFuture =
- mGameServiceConnector.post(gameService -> {
- gameService.disconnected();
- });
- mGameServiceConnector.unbind();
+ mGameServiceConnector.post(gameService -> {
+ gameService.disconnected();
+ }).whenComplete((result, t) -> {
+ mGameServiceConnector.unbind();
+ });
mGameSessionServiceConnector.unbind();
}
diff --git a/services/core/java/com/android/server/app/GameServiceProviderSelector.java b/services/core/java/com/android/server/app/GameServiceProviderSelector.java
index 0f55b9f..d125f21 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderSelector.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderSelector.java
@@ -26,10 +26,10 @@
interface GameServiceProviderSelector {
/**
- * Returns the {@link GameServiceProviderConfiguration} associated with the selected Game
+ * Returns the {@link GameServiceConfiguration} associated with the selected Game
* Service provider for the given user or {@code null} if none should be used.
*/
@Nullable
- GameServiceProviderConfiguration get(@Nullable SystemService.TargetUser user,
+ GameServiceConfiguration get(@Nullable SystemService.TargetUser user,
@Nullable String packageNameOverride);
}
diff --git a/services/core/java/com/android/server/app/GameServiceProviderSelectorImpl.java b/services/core/java/com/android/server/app/GameServiceProviderSelectorImpl.java
index c1ad668..fc85308 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderSelectorImpl.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderSelectorImpl.java
@@ -34,6 +34,7 @@
import android.util.Xml;
import com.android.server.SystemService;
+import com.android.server.app.GameServiceConfiguration.GameServiceComponentConfiguration;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -57,7 +58,7 @@
@Override
@Nullable
- public GameServiceProviderConfiguration get(@Nullable SystemService.TargetUser user,
+ public GameServiceConfiguration get(@Nullable SystemService.TargetUser user,
@Nullable String packageNameOverride) {
if (user == null) {
return null;
@@ -98,10 +99,10 @@
if (gameServiceResolveInfos == null || gameServiceResolveInfos.isEmpty()) {
Slog.w(TAG, "No available game service found for user id: " + userId);
- return null;
+ return new GameServiceConfiguration(gameServicePackage, null);
}
- GameServiceProviderConfiguration selectedProvider = null;
+ GameServiceConfiguration selectedProvider = null;
for (ResolveInfo resolveInfo : gameServiceResolveInfos) {
if (resolveInfo.serviceInfo == null) {
continue;
@@ -115,16 +116,18 @@
}
selectedProvider =
- new GameServiceProviderConfiguration(
- new UserHandle(userId),
- gameServiceServiceInfo.getComponentName(),
- gameSessionServiceComponentName);
+ new GameServiceConfiguration(
+ gameServicePackage,
+ new GameServiceComponentConfiguration(
+ new UserHandle(userId),
+ gameServiceServiceInfo.getComponentName(),
+ gameSessionServiceComponentName));
break;
}
if (selectedProvider == null) {
Slog.w(TAG, "No valid game service found for user id: " + userId);
- return null;
+ return new GameServiceConfiguration(gameServicePackage, null);
}
return selectedProvider;
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 9e87898..30ac1b8 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -3134,8 +3134,8 @@
writer.println("Domain verification status:");
writer.increaseIndent();
try {
- mDomainVerificationManager.printState(writer, packageName,
- UserHandle.USER_ALL, mSettings::getPackage);
+ mDomainVerificationManager.printState(this, writer, packageName,
+ UserHandle.USER_ALL);
} catch (Exception e) {
pw.println("Failure printing domain verification information");
Slog.e(TAG, "Failure printing domain verification information", e);
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 3220b31..58f9bb2 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -453,7 +453,8 @@
}
for (final int affectedUserId : affectedUserIds) {
if (hadSuspendAppsPermission.get(affectedUserId)) {
- mPm.unsuspendForSuspendingPackage(packageName, affectedUserId);
+ mPm.unsuspendForSuspendingPackage(mPm.snapshotComputer(), packageName,
+ affectedUserId);
mPm.removeAllDistractingPackageRestrictions(affectedUserId);
}
}
diff --git a/services/core/java/com/android/server/pm/DomainVerificationConnection.java b/services/core/java/com/android/server/pm/DomainVerificationConnection.java
index d24435e..db8c6dc 100644
--- a/services/core/java/com/android/server/pm/DomainVerificationConnection.java
+++ b/services/core/java/com/android/server/pm/DomainVerificationConnection.java
@@ -26,17 +26,12 @@
import android.os.Message;
import android.os.UserHandle;
-import com.android.internal.util.FunctionalUtils;
import com.android.server.DeviceIdleInternal;
import com.android.server.pm.parsing.pkg.AndroidPackage;
-import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.verify.domain.DomainVerificationService;
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV1;
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxyV2;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
public final class DomainVerificationConnection implements DomainVerificationService.Connection,
DomainVerificationProxyV1.Connection, DomainVerificationProxyV2.Connection {
final PackageManagerService mPm;
@@ -111,42 +106,8 @@
return mUmInternal.exists(userId);
}
- @Override
- public void withPackageSettingsSnapshot(
- @NonNull Consumer<Function<String, PackageStateInternal>> block) {
- mPmInternal.withPackageSettingsSnapshot(block);
- }
-
- @Override
- public <Output> Output withPackageSettingsSnapshotReturning(
- @NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageStateInternal>,
- Output> block) {
- return mPmInternal.withPackageSettingsSnapshotReturning(block);
- }
-
- @Override
- public <ExceptionType extends Exception> void withPackageSettingsSnapshotThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedConsumer<Function<String, PackageStateInternal>,
- ExceptionType> block) throws ExceptionType {
- mPmInternal.withPackageSettingsSnapshotThrowing(block);
- }
-
- @Override
- public <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
- withPackageSettingsSnapshotThrowing2(
- @NonNull FunctionalUtils.ThrowingChecked2Consumer<
- Function<String, PackageStateInternal>, ExceptionOne,
- ExceptionTwo> block)
- throws ExceptionOne, ExceptionTwo {
- mPmInternal.withPackageSettingsSnapshotThrowing2(block);
- }
-
- @Override
- public <Output, ExceptionType extends Exception> Output
- withPackageSettingsSnapshotReturningThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedFunction<
- Function<String, PackageStateInternal>, Output, ExceptionType> block)
- throws ExceptionType {
- return mPmInternal.withPackageSettingsSnapshotReturningThrowing(block);
+ @NonNull
+ public Computer snapshot() {
+ return (Computer) mPmInternal.snapshot();
}
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 234a230..c09c904 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -36,7 +36,6 @@
import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_SETUP;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
-import static android.content.pm.PackageManagerInternal.PACKAGE_SETUP_WIZARD;
import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile;
import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED;
@@ -145,6 +144,7 @@
import com.android.internal.content.InstallLocationUtils;
import com.android.internal.security.VerityUtils;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.EventLogTags;
import com.android.server.pm.dex.ArtManagerService;
@@ -2563,7 +2563,9 @@
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mPm.mLock) {
- size = mPm.mPendingBroadcasts.size();
+ final SparseArray<ArrayMap<String, ArrayList<String>>> userIdToPackagesToComponents =
+ mPm.mPendingBroadcasts.copiedMap();
+ size = userIdToPackagesToComponents.size();
if (size <= 0) {
// Nothing to be done. Just return
return;
@@ -2573,11 +2575,11 @@
uids = new int[size];
int i = 0; // filling out the above arrays
- for (int n = 0; n < mPm.mPendingBroadcasts.userIdCount(); n++) {
- final int packageUserId = mPm.mPendingBroadcasts.userIdAt(n);
+ for (int n = 0; n < size; n++) {
+ final int packageUserId = userIdToPackagesToComponents.keyAt(n);
final ArrayMap<String, ArrayList<String>> componentsToBroadcast =
- mPm.mPendingBroadcasts.packagesForUserId(packageUserId);
- final int numComponents = componentsToBroadcast.size();
+ userIdToPackagesToComponents.valueAt(n);
+ final int numComponents = CollectionUtils.size(componentsToBroadcast);
for (int index = 0; i < size && index < numComponents; index++) {
packages[i] = componentsToBroadcast.keyAt(index);
components[i] = componentsToBroadcast.valueAt(index);
diff --git a/services/core/java/com/android/server/pm/PackageHandler.java b/services/core/java/com/android/server/pm/PackageHandler.java
index 46e2aa3..b028a2c 100644
--- a/services/core/java/com/android/server/pm/PackageHandler.java
+++ b/services/core/java/com/android/server/pm/PackageHandler.java
@@ -382,6 +382,7 @@
case PRUNE_UNUSED_STATIC_SHARED_LIBRARIES: {
try {
mPm.mInjector.getSharedLibrariesImpl().pruneUnusedStaticSharedLibraries(
+ mPm.snapshotComputer(),
Long.MAX_VALUE,
Settings.Global.getLong(mPm.mContext.getContentResolver(),
Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0b7a6a7..c05faf1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -293,7 +293,6 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
-import java.util.function.Function;
/**
* Keep track of all those APKs everywhere.
@@ -1898,7 +1897,8 @@
t.traceEnd();
t.traceBegin("read user settings");
- mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(
+ mFirstBoot = !mSettings.readLPw(mLiveComputer,
+ mInjector.getUserManagerInternal().getUsers(
/* excludePartial= */ true,
/* excludeDying= */ false,
/* excludePreCreated= */ false));
@@ -2841,8 +2841,9 @@
}
if (file.getUsableSpace() >= bytes) return;
+ Computer computer = snapshotComputer();
// 5. Consider shared libraries with refcount=0 and age>min cache period
- if (internalVolume && mSharedLibraries.pruneUnusedStaticSharedLibraries(bytes,
+ if (internalVolume && mSharedLibraries.pruneUnusedStaticSharedLibraries(computer, bytes,
android.provider.Settings.Global.getLong(mContext.getContentResolver(),
Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
FREE_STORAGE_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD))) {
@@ -2854,14 +2855,12 @@
// 7. Consider installed instant apps unused longer than min cache period
if (internalVolume) {
- if (executeWithConsistentComputerReturning(computer ->
- mInstantAppRegistry.pruneInstalledInstantApps(computer, bytes,
- android.provider.Settings.Global.getLong(
- mContext.getContentResolver(),
- Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
- InstantAppRegistry
- .DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD)))
- ) {
+ if (mInstantAppRegistry.pruneInstalledInstantApps(computer, bytes,
+ android.provider.Settings.Global.getLong(
+ mContext.getContentResolver(),
+ Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+ InstantAppRegistry
+ .DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
return;
}
}
@@ -2881,14 +2880,12 @@
// 10. Consider instant meta-data (uninstalled apps) older that min cache period
if (internalVolume) {
- if (executeWithConsistentComputerReturning(computer ->
- mInstantAppRegistry.pruneUninstalledInstantApps(computer, bytes,
- android.provider.Settings.Global.getLong(
- mContext.getContentResolver(),
- Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
- InstantAppRegistry
- .DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD)))
- ) {
+ if (mInstantAppRegistry.pruneUninstalledInstantApps(computer, bytes,
+ android.provider.Settings.Global.getLong(
+ mContext.getContentResolver(),
+ Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+ InstantAppRegistry
+ .DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
return;
}
}
@@ -3493,8 +3490,8 @@
enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */,
false /* checkShell */, "getEphemeralApplications");
- List<InstantAppInfo> instantApps = executeWithConsistentComputerReturning(computer ->
- mInstantAppRegistry.getInstantApps(computer, userId));
+ Computer computer = snapshotComputer();
+ List<InstantAppInfo> instantApps = mInstantAppRegistry.getInstantApps(computer, userId);
if (instantApps != null) {
return new ParceledListSlice<>(instantApps);
}
@@ -3710,13 +3707,13 @@
public void notifyPackageUse(String packageName, int reason) {
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
- boolean notify = executeWithConsistentComputerReturning(computer -> {
- if (getInstantAppPackageName(callingUid) != null) {
- return isCallerSameApp(packageName, callingUid);
- } else {
- return !isInstantAppInternal(packageName, callingUserId, Process.SYSTEM_UID);
- }
- });
+ Computer computer = snapshotComputer();
+ final boolean notify;
+ if (getInstantAppPackageName(callingUid) != null) {
+ notify = isCallerSameApp(packageName, callingUid);
+ } else {
+ notify = !isInstantAppInternal(packageName, callingUserId, Process.SYSTEM_UID);
+ }
if (!notify) {
return;
}
@@ -4255,34 +4252,33 @@
final List<String> unactionedPackages = new ArrayList<>(packageNames.length);
ArraySet<String> changesToCommit = new ArraySet<>();
- executeWithConsistentComputer(computer -> {
- final boolean[] canRestrict = (restrictionFlags != 0)
- ? mSuspendPackageHelper.canSuspendPackageForUser(computer, packageNames, userId,
- callingUid) : null;
- for (int i = 0; i < packageNames.length; i++) {
- final String packageName = packageNames[i];
- final PackageStateInternal packageState =
- computer.getPackageStateInternal(packageName);
- if (packageState == null
- || shouldFilterApplication(packageState, callingUid, userId)) {
- Slog.w(TAG, "Could not find package setting for package: " + packageName
- + ". Skipping...");
- unactionedPackages.add(packageName);
- continue;
- }
- if (canRestrict != null && !canRestrict[i]) {
- unactionedPackages.add(packageName);
- continue;
- }
- final int oldDistractionFlags = packageState.getUserStateOrDefault(userId)
- .getDistractionFlags();
- if (restrictionFlags != oldDistractionFlags) {
- changedPackagesList.add(packageName);
- changedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
- changesToCommit.add(packageName);
- }
+ Computer computer = snapshotComputer();
+ final boolean[] canRestrict = (restrictionFlags != 0)
+ ? mSuspendPackageHelper.canSuspendPackageForUser(computer, packageNames, userId,
+ callingUid) : null;
+ for (int i = 0; i < packageNames.length; i++) {
+ final String packageName = packageNames[i];
+ final PackageStateInternal packageState =
+ computer.getPackageStateInternal(packageName);
+ if (packageState == null
+ || computer.shouldFilterApplication(packageState, callingUid, userId)) {
+ Slog.w(TAG, "Could not find package setting for package: " + packageName
+ + ". Skipping...");
+ unactionedPackages.add(packageName);
+ continue;
}
- });
+ if (canRestrict != null && !canRestrict[i]) {
+ unactionedPackages.add(packageName);
+ continue;
+ }
+ final int oldDistractionFlags = packageState.getUserStateOrDefault(userId)
+ .getDistractionFlags();
+ if (restrictionFlags != oldDistractionFlags) {
+ changedPackagesList.add(packageName);
+ changedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
+ changesToCommit.add(packageName);
+ }
+ }
commitPackageStateMutation(null, mutator -> {
final int size = changesToCommit.size();
@@ -4341,8 +4337,9 @@
final int callingUid = Binder.getCallingUid();
enforceCanSetPackagesSuspendedAsUser(callingPackage, callingUid, userId,
"setPackagesSuspendedAsUser");
- return mSuspendPackageHelper.setPackagesSuspended(packageNames, suspended, appExtras,
- launcherExtras, dialogInfo, callingPackage, userId, callingUid);
+ return mSuspendPackageHelper.setPackagesSuspended(snapshotComputer(), packageNames,
+ suspended, appExtras, launcherExtras, dialogInfo, callingPackage, userId,
+ callingUid);
}
@Override
@@ -4361,11 +4358,12 @@
return mComputer.isPackageSuspendedForUser(packageName, userId);
}
- void unsuspendForSuspendingPackage(String suspendingPackage, int userId) {
+ void unsuspendForSuspendingPackage(@NonNull Computer computer, String suspendingPackage,
+ @UserIdInt int userId) {
// TODO: This can be replaced by a special parameter to iterate all packages, rather than
// this weird pre-collect of all packages.
- final String[] allPackages = getPackageStates().keySet().toArray(new String[0]);
- mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(
+ final String[] allPackages = computer.getPackageStates().keySet().toArray(new String[0]);
+ mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(computer,
allPackages, suspendingPackage::equals, userId);
}
@@ -4424,7 +4422,7 @@
throw new SecurityException("Calling uid " + callingUid
+ " cannot query getUnsuspendablePackagesForUser for user " + userId);
}
- return mSuspendPackageHelper.getUnsuspendablePackagesForUser(
+ return mSuspendPackageHelper.getUnsuspendablePackagesForUser(snapshotComputer(),
packageNames, userId, callingUid);
}
@@ -4625,7 +4623,7 @@
return true;
};
PackageStateMutator.InitialState initialState = recordInitialState();
- boolean allowed = executeWithConsistentComputerReturningThrowing(implementation);
+ boolean allowed = implementation.apply(snapshotComputer());
if (allowed) {
// TODO: Need to lock around here to handle mSettings.addInstallerPackageNames,
// should find an alternative which avoids any race conditions
@@ -4635,7 +4633,7 @@
targetPackage, state -> state.setInstaller(installerPackageName));
if (result.isPackagesChanged() || result.isStateChanged()) {
synchronized (mPackageStateWriteLock) {
- allowed = executeWithConsistentComputerReturningThrowing(implementation);
+ allowed = implementation.apply(snapshotComputer());
if (allowed) {
commitPackageStateMutation(null, targetPackage,
state -> state.setInstaller(installerPackageName));
@@ -4685,12 +4683,12 @@
}
};
- PackageStateMutator.Result result = executeWithConsistentComputerReturning(implementation);
+ PackageStateMutator.Result result = implementation.apply(snapshotComputer());
if (result != null && result.isStateChanged() && !result.isSpecificPackageNull()) {
// TODO: Specific return value of what state changed?
// The installer on record might have changed, retry with lock
synchronized (mPackageStateWriteLock) {
- result = executeWithConsistentComputerReturning(implementation);
+ result = implementation.apply(snapshotComputer());
}
}
@@ -4988,7 +4986,7 @@
}
if (checkPermission(Manifest.permission.SUSPEND_APPS, packageName, userId)
== PERMISSION_GRANTED) {
- unsuspendForSuspendingPackage(packageName, userId);
+ unsuspendForSuspendingPackage(snapshotComputer(), packageName, userId);
removeAllDistractingPackageRestrictions(userId);
flushPackageRestrictionsAsUserInternalLocked(userId);
}
@@ -5080,17 +5078,7 @@
updateInstantAppInstallerLocked(packageName);
scheduleWritePackageRestrictions(userId);
- final ArrayList<String> pendingComponents = mPendingBroadcasts.get(userId, packageName);
- if (pendingComponents == null) {
- mPendingBroadcasts.put(userId, packageName, updatedComponents);
- } else {
- for (int i = 0; i < updatedComponents.size(); i++) {
- final String updatedComponent = updatedComponents.get(i);
- if (!pendingComponents.contains(updatedComponent)) {
- pendingComponents.add(updatedComponent);
- }
- }
- }
+ mPendingBroadcasts.addComponents(userId, packageName, updatedComponents);
if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
}
@@ -5278,7 +5266,8 @@
try {
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
TypedXmlSerializer serializer = Xml.resolveSerializer(output);
- mDomainVerificationManager.writeSettings(serializer, true, userId);
+ mDomainVerificationManager.writeSettings(snapshotComputer(), serializer, true,
+ userId);
return output.toByteArray();
}
} catch (Exception e) {
@@ -5301,7 +5290,7 @@
// User ID input isn't necessary here as it assumes the user integers match and that
// the only states inside the backup XML are for the target user.
- mDomainVerificationManager.restoreSettings(parser);
+ mDomainVerificationManager.restoreSettings(snapshotComputer(), parser);
input.close();
} catch (Exception e) {
if (DEBUG_BACKUP) {
@@ -5689,48 +5678,48 @@
int callingUid = Binder.getCallingUid();
String componentPkgName = componentName.getPackageName();
- boolean changed = executeWithConsistentComputerReturning(computer -> {
- int componentUid = getPackageUid(componentPkgName, 0, userId);
- if (!UserHandle.isSameApp(callingUid, componentUid)) {
- throw new SecurityException("The calling UID (" + callingUid + ")"
- + " does not match the target UID");
- }
+ Computer computer = snapshotComputer();
- String allowedCallerPkg =
- mContext.getString(R.string.config_overrideComponentUiPackage);
- if (TextUtils.isEmpty(allowedCallerPkg)) {
- throw new SecurityException( "There is no package defined as allowed to change a "
- + "component's label or icon");
- }
+ int componentUid = computer.getPackageUid(componentPkgName, 0, userId);
+ if (!UserHandle.isSameApp(callingUid, componentUid)) {
+ throw new SecurityException("The calling UID (" + callingUid + ")"
+ + " does not match the target UID");
+ }
- int allowedCallerUid = getPackageUid(allowedCallerPkg, PackageManager.MATCH_SYSTEM_ONLY,
- userId);
- if (allowedCallerUid == -1 || !UserHandle.isSameApp(callingUid, allowedCallerUid)) {
- throw new SecurityException("The calling UID (" + callingUid + ")"
- + " is not allowed to change a component's label or icon");
- }
- PackageStateInternal packageState = computer.getPackageStateInternal(componentPkgName);
- if (packageState == null || packageState.getPkg() == null
- || (!packageState.isSystem()
- && !packageState.getTransientState().isUpdatedSystemApp())) {
- throw new SecurityException(
- "Changing the label is not allowed for " + componentName);
- }
+ String allowedCallerPkg =
+ mContext.getString(R.string.config_overrideComponentUiPackage);
+ if (TextUtils.isEmpty(allowedCallerPkg)) {
+ throw new SecurityException( "There is no package defined as allowed to change a "
+ + "component's label or icon");
+ }
- if (!mComponentResolver.componentExists(componentName)) {
- throw new IllegalArgumentException("Component " + componentName + " not found");
- }
+ int allowedCallerUid = computer.getPackageUid(allowedCallerPkg,
+ PackageManager.MATCH_SYSTEM_ONLY, userId);
+ if (allowedCallerUid == -1 || !UserHandle.isSameApp(callingUid, allowedCallerUid)) {
+ throw new SecurityException("The calling UID (" + callingUid + ")"
+ + " is not allowed to change a component's label or icon");
+ }
+ PackageStateInternal packageState = computer.getPackageStateInternal(componentPkgName);
+ if (packageState == null || packageState.getPkg() == null
+ || (!packageState.isSystem()
+ && !packageState.getTransientState().isUpdatedSystemApp())) {
+ throw new SecurityException(
+ "Changing the label is not allowed for " + componentName);
+ }
- Pair<String, Integer> overrideLabelIcon = packageState.getUserStateOrDefault(userId)
- .getOverrideLabelIconForComponent(componentName);
+ if (!computer.getComponentResolver().componentExists(componentName)) {
+ throw new IllegalArgumentException("Component " + componentName + " not found");
+ }
- String existingLabel = overrideLabelIcon == null ? null : overrideLabelIcon.first;
- Integer existingIcon = overrideLabelIcon == null ? null : overrideLabelIcon.second;
+ Pair<String, Integer> overrideLabelIcon = packageState.getUserStateOrDefault(userId)
+ .getOverrideLabelIconForComponent(componentName);
- return !TextUtils.equals(existingLabel, nonLocalizedLabel)
- || !Objects.equals(existingIcon, icon);
- });
- if (!changed) {
+ String existingLabel = overrideLabelIcon == null ? null : overrideLabelIcon.first;
+ Integer existingIcon = overrideLabelIcon == null ? null : overrideLabelIcon.second;
+
+ if (TextUtils.equals(existingLabel, nonLocalizedLabel)
+ && Objects.equals(existingIcon, icon)) {
+ // Nothing changed
return;
}
@@ -5738,16 +5727,7 @@
state -> state.userState(userId)
.setComponentLabelIcon(componentName, nonLocalizedLabel, icon));
- ArrayList<String> components = mPendingBroadcasts.get(userId, componentPkgName);
- if (components == null) {
- components = new ArrayList<>();
- mPendingBroadcasts.put(userId, componentPkgName, components);
- }
-
- String className = componentName.getClassName();
- if (!components.contains(className)) {
- components.add(className);
- }
+ mPendingBroadcasts.addComponent(userId, componentPkgName, componentName.getClassName());
if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
@@ -5956,6 +5936,7 @@
// packageName -> list of components to send broadcasts now
final ArrayMap<String, ArrayList<String>> sendNowBroadcasts = new ArrayMap<>(targetSize);
synchronized (mLock) {
+ Computer computer = snapshotComputer();
boolean scheduleBroadcastMessage = false;
boolean isSynchronous = false;
boolean anyChanged = false;
@@ -5967,8 +5948,8 @@
// update enabled settings
final ComponentEnabledSetting setting = settings.get(i);
final String packageName = setting.getPackageName();
- if (!setEnabledSettingInternalLocked(pkgSettings.get(packageName), setting,
- userId, callingPackage)) {
+ if (!setEnabledSettingInternalLocked(computer, pkgSettings.get(packageName),
+ setting, userId, callingPackage)) {
continue;
}
anyChanged = true;
@@ -5979,26 +5960,18 @@
// collect broadcast list for the package
final String componentName = setting.isComponent()
? setting.getClassName() : packageName;
- ArrayList<String> componentList = sendNowBroadcasts.get(packageName);
- if (componentList == null) {
- componentList = mPendingBroadcasts.get(userId, packageName);
- }
- final boolean newPackage = componentList == null;
- if (newPackage) {
- componentList = new ArrayList<>();
- }
- if (!componentList.contains(componentName)) {
- componentList.add(componentName);
- }
if ((setting.getEnabledFlags() & PackageManager.DONT_KILL_APP) == 0) {
+ ArrayList<String> componentList = sendNowBroadcasts.get(packageName);
+ componentList = componentList == null ? new ArrayList<>() : componentList;
+ if (!componentList.contains(componentName)) {
+ componentList.add(componentName);
+ }
sendNowBroadcasts.put(packageName, componentList);
// Purge entry from pending broadcast list if another one exists already
// since we are sending one right away.
mPendingBroadcasts.remove(userId, packageName);
} else {
- if (newPackage) {
- mPendingBroadcasts.put(userId, packageName, componentList);
- }
+ mPendingBroadcasts.addComponent(userId, packageName, componentName);
scheduleBroadcastMessage = true;
}
}
@@ -6041,8 +6014,9 @@
}
}
- private boolean setEnabledSettingInternalLocked(PackageSetting pkgSetting,
- ComponentEnabledSetting setting, int userId, String callingPackage) {
+ private boolean setEnabledSettingInternalLocked(@NonNull Computer computer,
+ PackageSetting pkgSetting, ComponentEnabledSetting setting, @UserIdInt int userId,
+ String callingPackage) {
final int newState = setting.getEnabledState();
final String packageName = setting.getPackageName();
boolean success = false;
@@ -6061,7 +6035,7 @@
// This app should not generally be allowed to get disabled by the UI, but
// if it ever does, we don't want to end up with some of the user's apps
// permanently suspended.
- unsuspendForSuspendingPackage(packageName, userId);
+ unsuspendForSuspendingPackage(computer, packageName, userId);
removeAllDistractingPackageRestrictions(userId);
}
success = true;
@@ -6152,11 +6126,8 @@
public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
if (!mUserManager.exists(userId)) return;
final int callingUid = Binder.getCallingUid();
- Pair<Boolean, String> wasNotLaunchedAndInstallerPackageName =
- executeWithConsistentComputerReturningThrowing(computer -> {
- if (computer.getInstantAppPackageName(callingUid) != null) {
- return null;
- }
+ final Computer computer = snapshotComputer();
+ if (computer.getInstantAppPackageName(callingUid) == null) {
final int permission = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
@@ -6171,36 +6142,30 @@
true /* requireFullPermission */, true /* checkShell */, "stop package");
final PackageStateInternal packageState = computer.getPackageStateInternal(packageName);
- final PackageUserState PackageUserState = packageState == null
+ final PackageUserState packageUserState = packageState == null
? null : packageState.getUserStateOrDefault(userId);
- if (packageState == null
- || computer.shouldFilterApplication(packageState, callingUid, userId)
- || PackageUserState.isStopped() == stopped) {
- return null;
- }
+ if (packageState != null
+ && !computer.shouldFilterApplication(packageState, callingUid, userId)
+ && packageUserState.isStopped() != stopped) {
+ boolean wasNotLaunched = packageUserState.isNotLaunched();
+ commitPackageStateMutation(null, packageName, state -> {
+ PackageUserStateWrite userState = state.userState(userId);
+ userState.setStopped(stopped);
+ if (wasNotLaunched) {
+ userState.setNotLaunched(false);
+ }
+ });
- return Pair.create(PackageUserState.isNotLaunched(),
- packageState.getInstallSource().installerPackageName);
- });
- if (wasNotLaunchedAndInstallerPackageName != null) {
- boolean wasNotLaunched = wasNotLaunchedAndInstallerPackageName.first;
-
- commitPackageStateMutation(null, packageName, packageState -> {
- PackageUserStateWrite userState = packageState.userState(userId);
- userState.setStopped(stopped);
if (wasNotLaunched) {
- userState.setNotLaunched(false);
+ final String installerPackageName =
+ packageState.getInstallSource().installerPackageName;
+ if (installerPackageName != null) {
+ notifyFirstLaunch(packageName, installerPackageName, userId);
+ }
}
- });
- if (wasNotLaunched) {
- final String installerPackageName = wasNotLaunchedAndInstallerPackageName.second;
- if (installerPackageName != null) {
- notifyFirstLaunch(packageName, installerPackageName, userId);
- }
+ scheduleWritePackageRestrictions(userId);
}
-
- scheduleWritePackageRestrictions(userId);
}
// If this would cause the app to leave force-stop, then also make sure to unhibernate the
@@ -6687,7 +6652,7 @@
"Only package verification agents can read the verifier device identity");
synchronized (mLock) {
- return mSettings.getVerifierDeviceIdentityLPw();
+ return mSettings.getVerifierDeviceIdentityLPw(mLiveComputer);
}
}
@@ -7026,15 +6991,16 @@
@Override
public void removeAllNonSystemPackageSuspensions(int userId) {
- final String[] allPackages = mComputer.getAllAvailablePackageNames();
- mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(allPackages,
+ final Computer computer = snapshotComputer();
+ final String[] allPackages = computer.getAllAvailablePackageNames();
+ mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(computer, allPackages,
(suspendingPackage) -> !PLATFORM_PACKAGE_NAME.equals(suspendingPackage),
userId);
}
@Override
public void removeNonSystemPackageSuspensions(String packageName, int userId) {
- mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(
+ mSuspendPackageHelper.removeSuspensionsBySuspendingPackage(snapshotComputer(),
new String[]{packageName},
(suspendingPackage) -> !PLATFORM_PACKAGE_NAME.equals(suspendingPackage),
userId);
@@ -7233,29 +7199,29 @@
@Override
public void grantImplicitAccess(int userId, Intent intent,
int recipientAppId, int visibleUid, boolean direct, boolean retainOnUpdate) {
- boolean accessGranted = executeWithConsistentComputerReturning(computer -> {
- final AndroidPackage visiblePackage = computer.getPackage(visibleUid);
- final int recipientUid = UserHandle.getUid(userId, recipientAppId);
- if (visiblePackage == null || computer.getPackage(recipientUid) == null) {
- return false;
- }
+ Computer computer = snapshotComputer();
+ final AndroidPackage visiblePackage = computer.getPackage(visibleUid);
+ final int recipientUid = UserHandle.getUid(userId, recipientAppId);
+ if (visiblePackage == null || computer.getPackage(recipientUid) == null) {
+ return;
+ }
- final boolean instantApp = computer.isInstantAppInternal(
- visiblePackage.getPackageName(), userId, visibleUid);
- if (instantApp) {
- if (!direct) {
- // if the interaction that lead to this granting access to an instant app
- // was indirect (i.e.: URI permission grant), do not actually execute the
- // grant.
- return false;
- }
- return mInstantAppRegistry.grantInstantAccess(userId, intent,
- recipientAppId, UserHandle.getAppId(visibleUid) /*instantAppId*/);
- } else {
- return mAppsFilter.grantImplicitAccess(recipientUid, visibleUid,
- retainOnUpdate);
+ final boolean instantApp = computer.isInstantAppInternal(
+ visiblePackage.getPackageName(), userId, visibleUid);
+ final boolean accessGranted;
+ if (instantApp) {
+ if (!direct) {
+ // if the interaction that lead to this granting access to an instant app
+ // was indirect (i.e.: URI permission grant), do not actually execute the
+ // grant.
+ return;
}
- });
+ accessGranted = mInstantAppRegistry.grantInstantAccess(userId, intent,
+ recipientAppId, UserHandle.getAppId(visibleUid) /*instantAppId*/);
+ } else {
+ accessGranted = mAppsFilter.grantImplicitAccess(recipientUid, visibleUid,
+ retainOnUpdate);
+ }
if (accessGranted) {
ApplicationPackageManager.invalidateGetPackagesForUidCache();
@@ -7271,8 +7237,7 @@
@Override
public void pruneInstantApps() {
- executeWithConsistentComputer(computer ->
- mInstantAppRegistry.pruneInstantApps(computer));
+ mInstantAppRegistry.pruneInstantApps(snapshotComputer());
}
@Override
@@ -7680,7 +7645,8 @@
@Override
public void unsuspendForSuspendingPackage(final String packageName, int affectedUser) {
- PackageManagerService.this.unsuspendForSuspendingPackage(packageName, affectedUser);
+ PackageManagerService.this.unsuspendForSuspendingPackage(snapshotComputer(),
+ packageName, affectedUser);
}
@Override
@@ -7744,52 +7710,6 @@
}
@Override
- public void withPackageSettingsSnapshot(
- @NonNull Consumer<Function<String, PackageStateInternal>> block) {
- executeWithConsistentComputer(computer ->
- block.accept(computer::getPackageStateInternal));
- }
-
- @Override
- public <Output> Output withPackageSettingsSnapshotReturning(
- @NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageStateInternal>,
- Output> block) {
- return executeWithConsistentComputerReturning(computer ->
- block.apply(computer::getPackageStateInternal));
- }
-
- @Override
- public <ExceptionType extends Exception> void withPackageSettingsSnapshotThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedConsumer<Function<String,
- PackageStateInternal>, ExceptionType> block) throws ExceptionType {
- executeWithConsistentComputerThrowing(computer ->
- block.accept(computer::getPackageStateInternal));
- }
-
- @Override
- public <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
- withPackageSettingsSnapshotThrowing2(
- @NonNull FunctionalUtils.ThrowingChecked2Consumer<
- Function<String, PackageStateInternal>, ExceptionOne,
- ExceptionTwo> block)
- throws ExceptionOne, ExceptionTwo {
- executeWithConsistentComputerThrowing2(
- (FunctionalUtils.ThrowingChecked2Consumer<Computer, ExceptionOne,
- ExceptionTwo>) computer -> block.accept(computer::getPackageStateInternal));
- }
-
- @Override
- public <Output, ExceptionType extends Exception> Output
- withPackageSettingsSnapshotReturningThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedFunction<
- Function<String, PackageStateInternal>, Output,
- ExceptionType> block)
- throws ExceptionType {
- return executeWithConsistentComputerReturningThrowing(computer ->
- block.apply(computer::getPackageStateInternal));
- }
-
- @Override
public void reconcileAppsData(int userId, @StorageManager.StorageFlags int flags,
boolean migrateAppsData) {
PackageManagerService.this.mAppDataHelper.reconcileAppsData(userId, flags,
@@ -7834,70 +7754,59 @@
@NonNull Set<String> outUpdatedPackageNames) {
synchronized (mOverlayPathsLock) {
final ArrayMap<String, ArraySet<String>> libNameToModifiedDependents = new ArrayMap<>();
- Boolean targetModified = executeWithConsistentComputerReturning(computer -> {
- final PackageStateInternal packageState = computer.getPackageStateInternal(
- targetPackageName);
- final AndroidPackage targetPkg =
- packageState == null ? null : packageState.getPkg();
- if (targetPackageName == null || targetPkg == null) {
- Slog.e(TAG, "failed to find package " + targetPackageName);
- return null;
- }
-
- if (Objects.equals(packageState.getUserStateOrDefault(userId).getOverlayPaths(),
- newOverlayPaths)) {
- return false;
- }
-
- if (targetPkg.getLibraryNames() != null) {
- // Set the overlay paths for dependencies of the shared library.
- for (final String libName : targetPkg.getLibraryNames()) {
- ArraySet<String> modifiedDependents = null;
-
- final SharedLibraryInfo info = computer.getSharedLibraryInfo(libName,
- SharedLibraryInfo.VERSION_UNDEFINED);
- if (info == null) {
- continue;
- }
- final List<VersionedPackage> dependents = computer
- .getPackagesUsingSharedLibrary(info, 0, Process.SYSTEM_UID, userId);
- if (dependents == null) {
- continue;
- }
- for (final VersionedPackage dependent : dependents) {
- final PackageStateInternal dependentState =
- computer.getPackageStateInternal(dependent.getPackageName());
- if (dependentState == null) {
- continue;
- }
- if (!Objects.equals(dependentState.getUserStateOrDefault(userId)
- .getSharedLibraryOverlayPaths()
- .get(libName), newOverlayPaths)) {
- String dependentPackageName = dependent.getPackageName();
- modifiedDependents = ArrayUtils.add(modifiedDependents,
- dependentPackageName);
- outUpdatedPackageNames.add(dependentPackageName);
- }
- }
-
- if (modifiedDependents != null) {
- libNameToModifiedDependents.put(libName, modifiedDependents);
- }
- }
- }
-
- outUpdatedPackageNames.add(targetPackageName);
- return true;
- });
-
- if (targetModified == null) {
- // Null indicates error
+ Computer computer = snapshotComputer();
+ final PackageStateInternal packageState = computer.getPackageStateInternal(
+ targetPackageName);
+ final AndroidPackage targetPkg = packageState == null ? null : packageState.getPkg();
+ if (targetPackageName == null || targetPkg == null) {
+ Slog.e(TAG, "failed to find package " + targetPackageName);
return false;
- } else if (!targetModified) {
- // Treat non-modification as a successful commit
+ }
+
+ if (Objects.equals(packageState.getUserStateOrDefault(userId).getOverlayPaths(),
+ newOverlayPaths)) {
return true;
}
+ if (targetPkg.getLibraryNames() != null) {
+ // Set the overlay paths for dependencies of the shared library.
+ for (final String libName : targetPkg.getLibraryNames()) {
+ ArraySet<String> modifiedDependents = null;
+
+ final SharedLibraryInfo info = computer.getSharedLibraryInfo(libName,
+ SharedLibraryInfo.VERSION_UNDEFINED);
+ if (info == null) {
+ continue;
+ }
+ final List<VersionedPackage> dependents = computer
+ .getPackagesUsingSharedLibrary(info, 0, Process.SYSTEM_UID, userId);
+ if (dependents == null) {
+ continue;
+ }
+ for (final VersionedPackage dependent : dependents) {
+ final PackageStateInternal dependentState =
+ computer.getPackageStateInternal(dependent.getPackageName());
+ if (dependentState == null) {
+ continue;
+ }
+ if (!Objects.equals(dependentState.getUserStateOrDefault(userId)
+ .getSharedLibraryOverlayPaths()
+ .get(libName), newOverlayPaths)) {
+ String dependentPackageName = dependent.getPackageName();
+ modifiedDependents = ArrayUtils.add(modifiedDependents,
+ dependentPackageName);
+ outUpdatedPackageNames.add(dependentPackageName);
+ }
+ }
+
+ if (modifiedDependents != null) {
+ libNameToModifiedDependents.put(libName, modifiedDependents);
+ }
+ }
+ }
+
+ outUpdatedPackageNames.add(targetPackageName);
+
commitPackageStateMutation(null, mutator -> {
mutator.forPackage(targetPackageName)
.userState(userId)
@@ -8062,36 +7971,6 @@
forEachPackageState(mComputer.getPackageStates(), actionWrapped);
}
- // TODO: Make private
- void executeWithConsistentComputer(
- @NonNull FunctionalUtils.ThrowingConsumer<Computer> consumer) {
- consumer.accept(snapshotComputer());
- }
-
- private <T> T executeWithConsistentComputerReturning(
- @NonNull FunctionalUtils.ThrowingFunction<Computer, T> function) {
- return function.apply(snapshotComputer());
- }
-
- private <ExceptionType extends Exception> void executeWithConsistentComputerThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedConsumer<Computer, ExceptionType> consumer)
- throws ExceptionType {
- consumer.accept(snapshotComputer());
- }
-
- private <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
- executeWithConsistentComputerThrowing2(
- @NonNull FunctionalUtils.ThrowingChecked2Consumer<Computer, ExceptionOne,
- ExceptionTwo> consumer) throws ExceptionOne, ExceptionTwo {
- consumer.accept(snapshotComputer());
- }
-
- private <T, ExceptionType extends Exception> T executeWithConsistentComputerReturningThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedFunction<Computer, T, ExceptionType> function)
- throws ExceptionType {
- return function.apply(snapshotComputer());
- }
-
boolean isHistoricalPackageUsageAvailable() {
return mPackageUsage.isHistoricalPackageUsageAvailable();
}
@@ -8357,7 +8236,7 @@
*/
void writeSettingsLPrTEMP() {
mPermissionManager.writeLegacyPermissionsTEMP(mSettings.mPermissions);
- mSettings.writeLPr();
+ mSettings.writeLPr(mLiveComputer);
}
@Override
@@ -8856,7 +8735,6 @@
}
void notifyInstantAppPackageInstalled(String packageName, int[] newUsers) {
- executeWithConsistentComputer(computer ->
- mInstantAppRegistry.onPackageInstalled(computer, packageName, newUsers));
+ mInstantAppRegistry.onPackageInstalled(snapshotComputer(), packageName, newUsers);
}
}
diff --git a/services/core/java/com/android/server/pm/PendingPackageBroadcasts.java b/services/core/java/com/android/server/pm/PendingPackageBroadcasts.java
index 4e9a06a..6e2f756 100644
--- a/services/core/java/com/android/server/pm/PendingPackageBroadcasts.java
+++ b/services/core/java/com/android/server/pm/PendingPackageBroadcasts.java
@@ -16,12 +16,17 @@
package com.android.server.pm;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.util.ArrayMap;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
+import java.util.List;
/**
* Set of pending broadcasts for aggregating enable/disable of components.
@@ -29,65 +34,111 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public final class PendingPackageBroadcasts {
+ private final Object mLock = new PackageManagerTracedLock();
+
// for each user id, a map of <package name -> components within that package>
+ @GuardedBy("mLock")
final SparseArray<ArrayMap<String, ArrayList<String>>> mUidMap;
public PendingPackageBroadcasts() {
mUidMap = new SparseArray<>(2);
}
- public ArrayList<String> get(int userId, String packageName) {
- ArrayMap<String, ArrayList<String>> packages = getOrAllocate(userId);
- return packages.get(packageName);
+ public boolean hasPackage(@UserIdInt int userId, @NonNull String packageName) {
+ synchronized (mLock) {
+ final ArrayMap<String, ArrayList<String>> packages = mUidMap.get(userId);
+ return packages != null && packages.containsKey(packageName);
+ }
}
public void put(int userId, String packageName, ArrayList<String> components) {
- ArrayMap<String, ArrayList<String>> packages = getOrAllocate(userId);
- packages.put(packageName, components);
+ synchronized (mLock) {
+ ArrayMap<String, ArrayList<String>> packages = getOrAllocate(userId);
+ packages.put(packageName, components);
+ }
+ }
+
+ public void addComponent(@UserIdInt int userId, @NonNull String packageName,
+ @NonNull String componentClassName) {
+ synchronized (mLock) {
+ ArrayList<String> components = getOrAllocate(userId, packageName);
+ if (!components.contains(componentClassName)) {
+ components.add(componentClassName);
+ }
+ }
+ }
+
+ public void addComponents(@UserIdInt int userId, @NonNull String packageName,
+ @NonNull List<String> componentClassNames) {
+ synchronized (mLock) {
+ ArrayList<String> components = getOrAllocate(userId, packageName);
+ for (int index = 0; index < componentClassNames.size(); index++) {
+ String componentClassName = componentClassNames.get(index);
+ if (!components.contains(componentClassName)) {
+ components.add(componentClassName);
+ }
+ }
+ }
}
public void remove(int userId, String packageName) {
- ArrayMap<String, ArrayList<String>> packages = mUidMap.get(userId);
- if (packages != null) {
- packages.remove(packageName);
+ synchronized (mLock) {
+ ArrayMap<String, ArrayList<String>> packages = mUidMap.get(userId);
+ if (packages != null) {
+ packages.remove(packageName);
+ }
}
}
public void remove(int userId) {
- mUidMap.remove(userId);
- }
-
- public int userIdCount() {
- return mUidMap.size();
- }
-
- public int userIdAt(int n) {
- return mUidMap.keyAt(n);
- }
-
- public ArrayMap<String, ArrayList<String>> packagesForUserId(int userId) {
- return mUidMap.get(userId);
- }
-
- public int size() {
- // total number of pending broadcast entries across all userIds
- int num = 0;
- for (int i = 0; i < mUidMap.size(); i++) {
- num += mUidMap.valueAt(i).size();
+ synchronized (mLock) {
+ mUidMap.remove(userId);
}
- return num;
+ }
+
+ @Nullable
+ public SparseArray<ArrayMap<String, ArrayList<String>>> copiedMap() {
+ synchronized (mLock) {
+ SparseArray<ArrayMap<String, ArrayList<String>>> copy = new SparseArray<>();
+ for (int userIdIndex = 0; userIdIndex < mUidMap.size(); userIdIndex++) {
+ final ArrayMap<String, ArrayList<String>> packages = mUidMap.valueAt(userIdIndex);
+ ArrayMap<String, ArrayList<String>> packagesCopy = new ArrayMap<>();
+ for (int packagesIndex = 0; packagesIndex < packages.size(); packagesIndex++) {
+ packagesCopy.put(packages.keyAt(packagesIndex),
+ new ArrayList<>(packages.valueAt(packagesIndex)));
+ }
+ copy.put(mUidMap.keyAt(userIdIndex), packagesCopy);
+ }
+ return copy;
+ }
}
public void clear() {
- mUidMap.clear();
+ synchronized (mLock) {
+ mUidMap.clear();
+ }
}
private ArrayMap<String, ArrayList<String>> getOrAllocate(int userId) {
- ArrayMap<String, ArrayList<String>> map = mUidMap.get(userId);
- if (map == null) {
- map = new ArrayMap<>();
- mUidMap.put(userId, map);
+ synchronized (mLock) {
+ ArrayMap<String, ArrayList<String>> map = mUidMap.get(userId);
+ if (map == null) {
+ map = new ArrayMap<>();
+ mUidMap.put(userId, map);
+ }
+ return map;
}
- return map;
+ }
+
+ private ArrayList<String> getOrAllocate(int userId, @NonNull String packageName) {
+ synchronized (mLock) {
+ ArrayMap<String, ArrayList<String>> map = mUidMap.get(userId);
+ if (map == null) {
+ map = new ArrayMap<>();
+ mUidMap.put(userId, map);
+ }
+
+ return map.computeIfAbsent(packageName, k -> new ArrayList<>());
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 2ad35b7..394c8fb 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2432,7 +2432,7 @@
}
}
- void writeLPr() {
+ void writeLPr(@NonNull Computer computer) {
//Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
final long startTime = SystemClock.uptimeMillis();
@@ -2524,8 +2524,8 @@
}
}
- mDomainVerificationManager.writeSettings(serializer, false /* includeSignatures */,
- UserHandle.USER_ALL);
+ mDomainVerificationManager.writeSettings(computer, serializer,
+ false /* includeSignatures */, UserHandle.USER_ALL);
mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
@@ -2967,7 +2967,7 @@
}
}
- boolean readLPw(@NonNull List<UserInfo> users) {
+ boolean readLPw(@NonNull Computer computer, @NonNull List<UserInfo> users) {
FileInputStream str = null;
if (mBackupSettingsFilename.exists()) {
try {
@@ -3111,7 +3111,7 @@
ver.databaseVersion = parser.getAttributeInt(null, ATTR_DATABASE_VERSION);
ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
} else if (tagName.equals(DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) {
- mDomainVerificationManager.readSettings(parser);
+ mDomainVerificationManager.readSettings(computer, parser);
} else if (tagName.equals(
DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) {
mDomainVerificationManager.readLegacySettings(parser);
@@ -4287,11 +4287,11 @@
return Process.FIRST_APPLICATION_UID + size;
}
- public VerifierDeviceIdentity getVerifierDeviceIdentityLPw() {
+ public VerifierDeviceIdentity getVerifierDeviceIdentityLPw(@NonNull Computer computer) {
if (mVerifierDeviceIdentity == null) {
mVerifierDeviceIdentity = VerifierDeviceIdentity.generate();
- writeLPr();
+ writeLPr(computer);
}
return mVerifierDeviceIdentity;
diff --git a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
index 0638d5e..3fe0790 100644
--- a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
+++ b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
@@ -321,7 +321,8 @@
* on the device.
* @return {@code true} if the available storage space is reached.
*/
- boolean pruneUnusedStaticSharedLibraries(long neededSpace, long maxCachePeriod)
+ boolean pruneUnusedStaticSharedLibraries(@NonNull Computer computer, long neededSpace,
+ long maxCachePeriod)
throws IOException {
final StorageManager storage = mInjector.getSystemService(StorageManager.class);
final File volume = storage.findPathForUuid(StorageManager.UUID_PRIVATE_INTERNAL);
@@ -332,38 +333,36 @@
// Important: We skip shared libs used for some user since
// in such a case we need to keep the APK on the device. The check for
// a lib being used for any user is performed by the uninstall call.
- mPm.executeWithConsistentComputer(computer -> {
- final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
- sharedLibraries = computer.getSharedLibraries();
- final int libCount = sharedLibraries.size();
- for (int i = 0; i < libCount; i++) {
- final WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
- sharedLibraries.valueAt(i);
- if (versionedLib == null) {
+ final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
+ sharedLibraries = computer.getSharedLibraries();
+ final int libCount = sharedLibraries.size();
+ for (int i = 0; i < libCount; i++) {
+ final WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
+ sharedLibraries.valueAt(i);
+ if (versionedLib == null) {
+ continue;
+ }
+ final int versionCount = versionedLib.size();
+ for (int j = 0; j < versionCount; j++) {
+ SharedLibraryInfo libInfo = versionedLib.valueAt(j);
+ final PackageStateInternal ps = getLibraryPackage(computer, libInfo);
+ if (ps == null) {
continue;
}
- final int versionCount = versionedLib.size();
- for (int j = 0; j < versionCount; j++) {
- SharedLibraryInfo libInfo = versionedLib.valueAt(j);
- final PackageStateInternal ps = getLibraryPackage(computer, libInfo);
- if (ps == null) {
- continue;
- }
- // Skip unused libs cached less than the min period to prevent pruning a lib
- // needed by a subsequently installed package.
- if (now - ps.getLastUpdateTime() < maxCachePeriod) {
- continue;
- }
-
- if (ps.getPkg().isSystem()) {
- continue;
- }
-
- packagesToDelete.add(new VersionedPackage(ps.getPkg().getPackageName(),
- libInfo.getDeclaringPackage().getLongVersionCode()));
+ // Skip unused libs cached less than the min period to prevent pruning a lib
+ // needed by a subsequently installed package.
+ if (now - ps.getLastUpdateTime() < maxCachePeriod) {
+ continue;
}
+
+ if (ps.getPkg().isSystem()) {
+ continue;
+ }
+
+ packagesToDelete.add(new VersionedPackage(ps.getPkg().getPackageName(),
+ libInfo.getDeclaringPackage().getLongVersionCode()));
}
- });
+ }
final int packageCount = packagesToDelete.size();
for (int i = 0; i < packageCount; i++) {
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index bd1c9c7..3ef5599 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -27,6 +27,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.Intent;
@@ -99,10 +100,10 @@
* @return The names of failed packages.
*/
@Nullable
- String[] setPackagesSuspended(@Nullable String[] packageNames, boolean suspended,
- @Nullable PersistableBundle appExtras, @Nullable PersistableBundle launcherExtras,
- @Nullable SuspendDialogInfo dialogInfo, @NonNull String callingPackage,
- int userId, int callingUid) {
+ String[] setPackagesSuspended(@NonNull Computer computer, @Nullable String[] packageNames,
+ boolean suspended, @Nullable PersistableBundle appExtras,
+ @Nullable PersistableBundle launcherExtras, @Nullable SuspendDialogInfo dialogInfo,
+ @NonNull String callingPackage, @UserIdInt int userId, int callingUid) {
if (ArrayUtils.isEmpty(packageNames)) {
return packageNames;
}
@@ -121,62 +122,60 @@
ArraySet<String> modifiedPackages = new ArraySet<>();
- mPm.executeWithConsistentComputer(computer -> {
- final boolean[] canSuspend = suspended
- ? canSuspendPackageForUser(computer, packageNames, userId, callingUid) : null;
- for (int i = 0; i < packageNames.length; i++) {
- final String packageName = packageNames[i];
- if (callingPackage.equals(packageName)) {
- Slog.w(TAG, "Calling package: " + callingPackage + " trying to "
- + (suspended ? "" : "un") + "suspend itself. Ignoring");
- unmodifiablePackages.add(packageName);
- continue;
- }
- final PackageStateInternal packageState =
- computer.getPackageStateInternal(packageName);
- if (packageState == null
- || computer.shouldFilterApplication(packageState, callingUid, userId)) {
- Slog.w(TAG, "Could not find package setting for package: " + packageName
- + ". Skipping suspending/un-suspending.");
- unmodifiablePackages.add(packageName);
- continue;
- }
- if (canSuspend != null && !canSuspend[i]) {
- unmodifiablePackages.add(packageName);
- continue;
- }
+ final boolean[] canSuspend = suspended
+ ? canSuspendPackageForUser(computer, packageNames, userId, callingUid) : null;
+ for (int i = 0; i < packageNames.length; i++) {
+ final String packageName = packageNames[i];
+ if (callingPackage.equals(packageName)) {
+ Slog.w(TAG, "Calling package: " + callingPackage + " trying to "
+ + (suspended ? "" : "un") + "suspend itself. Ignoring");
+ unmodifiablePackages.add(packageName);
+ continue;
+ }
+ final PackageStateInternal packageState =
+ computer.getPackageStateInternal(packageName);
+ if (packageState == null
+ || computer.shouldFilterApplication(packageState, callingUid, userId)) {
+ Slog.w(TAG, "Could not find package setting for package: " + packageName
+ + ". Skipping suspending/un-suspending.");
+ unmodifiablePackages.add(packageName);
+ continue;
+ }
+ if (canSuspend != null && !canSuspend[i]) {
+ unmodifiablePackages.add(packageName);
+ continue;
+ }
- final WatchedArrayMap<String, SuspendParams> suspendParamsMap =
- packageState.getUserStateOrDefault(userId).getSuspendParams();
- if (suspended) {
- if (suspendParamsMap != null && suspendParamsMap.containsKey(packageName)) {
- final SuspendParams suspendParams = suspendParamsMap.get(packageName);
- // Skip if there's no changes
- if (suspendParams != null
- && Objects.equals(suspendParams.getDialogInfo(), dialogInfo)
- && Objects.equals(suspendParams.getAppExtras(), appExtras)
- && Objects.equals(suspendParams.getLauncherExtras(),
- launcherExtras)) {
- // Carried over API behavior, must notify change even if no change
- changedPackagesList.add(packageName);
- changedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
- continue;
- }
+ final WatchedArrayMap<String, SuspendParams> suspendParamsMap =
+ packageState.getUserStateOrDefault(userId).getSuspendParams();
+ if (suspended) {
+ if (suspendParamsMap != null && suspendParamsMap.containsKey(packageName)) {
+ final SuspendParams suspendParams = suspendParamsMap.get(packageName);
+ // Skip if there's no changes
+ if (suspendParams != null
+ && Objects.equals(suspendParams.getDialogInfo(), dialogInfo)
+ && Objects.equals(suspendParams.getAppExtras(), appExtras)
+ && Objects.equals(suspendParams.getLauncherExtras(),
+ launcherExtras)) {
+ // Carried over API behavior, must notify change even if no change
+ changedPackagesList.add(packageName);
+ changedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
+ continue;
}
}
-
- // If size one, the package will be unsuspended from this call
- boolean packageUnsuspended =
- !suspended && CollectionUtils.size(suspendParamsMap) <= 1;
- if (suspended || packageUnsuspended) {
- changedPackagesList.add(packageName);
- changedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
- }
-
- modifiedPackages.add(packageName);
- modifiedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
}
- });
+
+ // If size one, the package will be unsuspended from this call
+ boolean packageUnsuspended =
+ !suspended && CollectionUtils.size(suspendParamsMap) <= 1;
+ if (suspended || packageUnsuspended) {
+ changedPackagesList.add(packageName);
+ changedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
+ }
+
+ modifiedPackages.add(packageName);
+ modifiedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
+ }
mPm.commitPackageStateMutation(null, mutator -> {
final int size = modifiedPackages.size();
@@ -218,29 +217,27 @@
* @return The names of packages which are Unsuspendable.
*/
@NonNull
- String[] getUnsuspendablePackagesForUser(@NonNull String[] packageNames, int userId,
- int callingUid) {
+ String[] getUnsuspendablePackagesForUser(@NonNull Computer computer,
+ @NonNull String[] packageNames, @UserIdInt int userId, int callingUid) {
if (!isSuspendAllowedForUser(userId, callingUid)) {
Slog.w(TAG, "Cannot suspend due to restrictions on user " + userId);
return packageNames;
}
final ArraySet<String> unactionablePackages = new ArraySet<>();
- mPm.executeWithConsistentComputer(computer -> {
- final boolean[] canSuspend = canSuspendPackageForUser(computer, packageNames, userId,
- callingUid);
- for (int i = 0; i < packageNames.length; i++) {
- if (!canSuspend[i]) {
- unactionablePackages.add(packageNames[i]);
- continue;
- }
- final PackageStateInternal packageState =
- computer.getPackageStateFiltered(packageNames[i], callingUid, userId);
- if (packageState == null) {
- Slog.w(TAG, "Could not find package setting for package: " + packageNames[i]);
- unactionablePackages.add(packageNames[i]);
- }
+ final boolean[] canSuspend = canSuspendPackageForUser(computer, packageNames, userId,
+ callingUid);
+ for (int i = 0; i < packageNames.length; i++) {
+ if (!canSuspend[i]) {
+ unactionablePackages.add(packageNames[i]);
+ continue;
}
- });
+ final PackageStateInternal packageState =
+ computer.getPackageStateFiltered(packageNames[i], callingUid, userId);
+ if (packageState == null) {
+ Slog.w(TAG, "Could not find package setting for package: " + packageNames[i]);
+ unactionablePackages.add(packageNames[i]);
+ }
+ }
return unactionablePackages.toArray(new String[unactionablePackages.size()]);
}
@@ -282,45 +279,44 @@
* suspensions will be removed.
* @param userId The user for which the changes are taking place.
*/
- void removeSuspensionsBySuspendingPackage(@NonNull String[] packagesToChange,
+ void removeSuspensionsBySuspendingPackage(@NonNull Computer computer,
+ @NonNull String[] packagesToChange,
@NonNull Predicate<String> suspendingPackagePredicate, int userId) {
final List<String> unsuspendedPackages = new ArrayList<>();
final IntArray unsuspendedUids = new IntArray();
final ArrayMap<String, ArraySet<String>> pkgToSuspendingPkgsToCommit = new ArrayMap<>();
- mPm.executeWithConsistentComputer(computer -> {
- for (String packageName : packagesToChange) {
- final PackageStateInternal packageState =
- computer.getPackageStateInternal(packageName);
- final PackageUserStateInternal packageUserState = packageState == null
- ? null : packageState.getUserStateOrDefault(userId);
- if (packageUserState == null || !packageUserState.isSuspended()) {
- continue;
- }
+ for (String packageName : packagesToChange) {
+ final PackageStateInternal packageState =
+ computer.getPackageStateInternal(packageName);
+ final PackageUserStateInternal packageUserState = packageState == null
+ ? null : packageState.getUserStateOrDefault(userId);
+ if (packageUserState == null || !packageUserState.isSuspended()) {
+ continue;
+ }
- WatchedArrayMap<String, SuspendParams> suspendParamsMap =
- packageUserState.getSuspendParams();
- int countRemoved = 0;
- for (int index = 0; index < suspendParamsMap.size(); index++) {
- String suspendingPackage = suspendParamsMap.keyAt(index);
- if (suspendingPackagePredicate.test(suspendingPackage)) {
- ArraySet<String> suspendingPkgsToCommit =
- pkgToSuspendingPkgsToCommit.get(packageName);
- if (suspendingPkgsToCommit == null) {
- suspendingPkgsToCommit = new ArraySet<>();
- pkgToSuspendingPkgsToCommit.put(packageName, suspendingPkgsToCommit);
- }
- suspendingPkgsToCommit.add(suspendingPackage);
- countRemoved++;
+ WatchedArrayMap<String, SuspendParams> suspendParamsMap =
+ packageUserState.getSuspendParams();
+ int countRemoved = 0;
+ for (int index = 0; index < suspendParamsMap.size(); index++) {
+ String suspendingPackage = suspendParamsMap.keyAt(index);
+ if (suspendingPackagePredicate.test(suspendingPackage)) {
+ ArraySet<String> suspendingPkgsToCommit =
+ pkgToSuspendingPkgsToCommit.get(packageName);
+ if (suspendingPkgsToCommit == null) {
+ suspendingPkgsToCommit = new ArraySet<>();
+ pkgToSuspendingPkgsToCommit.put(packageName, suspendingPkgsToCommit);
}
- }
-
- // Everything would be removed and package unsuspended
- if (countRemoved == suspendParamsMap.size()) {
- unsuspendedPackages.add(packageState.getPackageName());
- unsuspendedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
+ suspendingPkgsToCommit.add(suspendingPackage);
+ countRemoved++;
}
}
- });
+
+ // Everything would be removed and package unsuspended
+ if (countRemoved == suspendParamsMap.size()) {
+ unsuspendedPackages.add(packageState.getPackageName());
+ unsuspendedUids.add(UserHandle.getUid(userId, packageState.getAppId()));
+ }
+ }
mPm.commitPackageStateMutation(null, mutator -> {
for (int mapIndex = 0; mapIndex < pkgToSuspendingPkgsToCommit.size(); mapIndex++) {
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java
index b730ab2..e06b608 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationDebug.java
@@ -30,6 +30,7 @@
import android.util.SparseArray;
import com.android.internal.util.CollectionUtils;
+import com.android.server.pm.Computer;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState;
@@ -38,7 +39,6 @@
import java.util.Arrays;
import java.util.List;
-import java.util.function.Function;
@SuppressWarnings("PointlessBooleanExpression")
public class DomainVerificationDebug {
@@ -62,8 +62,7 @@
}
public void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName,
- @Nullable @UserIdInt Integer userId,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction,
+ @Nullable @UserIdInt Integer userId, @NonNull Computer snapshot,
@NonNull DomainVerificationStateMap<DomainVerificationPkgState> stateMap)
throws NameNotFoundException {
ArrayMap<String, Integer> reusedMap = new ArrayMap<>();
@@ -74,7 +73,7 @@
for (int index = 0; index < size; index++) {
DomainVerificationPkgState pkgState = stateMap.valueAt(index);
String pkgName = pkgState.getPackageName();
- PackageStateInternal pkgSetting = pkgSettingFunction.apply(pkgName);
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName);
if (pkgSetting == null || pkgSetting.getPkg() == null) {
continue;
}
@@ -90,7 +89,7 @@
throw DomainVerificationUtils.throwPackageUnavailable(packageName);
}
- PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName);
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName);
if (pkgSetting == null || pkgSetting.getPkg() == null) {
throw DomainVerificationUtils.throwPackageUnavailable(packageName);
}
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
index 25147d0..1714086 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
@@ -25,7 +25,6 @@
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageSettingsSnapshotProvider;
import android.content.pm.ResolveInfo;
import android.content.pm.verify.domain.DomainVerificationInfo;
import android.content.pm.verify.domain.DomainVerificationManager;
@@ -37,7 +36,7 @@
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
-import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.Computer;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.Settings;
import com.android.server.pm.pkg.PackageStateInternal;
@@ -227,14 +226,14 @@
* assumed nothing has changed since the device rebooted.
* <p>
* If this is a new install, state will be restored from a previous call to {@link
- * #restoreSettings(TypedXmlPullParser)}, or a new one will be generated. In either case, a
+ * #restoreSettings(Computer, TypedXmlPullParser)}, or a new one will be generated. In either case, a
* broadcast will be sent to the domain verification agent so it may re-run any verification
* logic for the newly associated domains.
* <p>
* This will mutate internal {@link DomainVerificationPkgState} and so will hold the internal
* lock. This should never be called from within the domain verification classes themselves.
* <p>
- * This will NOT call {@link #writeSettings(TypedXmlSerializer, boolean, int)}. That must be
+ * This will NOT call {@link #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. That must be
* handled by the caller.
*/
void addPackage(@NonNull PackageStateInternal newPkgSetting);
@@ -249,7 +248,7 @@
* This will mutate internal {@link DomainVerificationPkgState} and so will hold the internal
* lock. This should never be called from within the domain verification classes themselves.
* <p>
- * This will NOT call {@link #writeSettings(TypedXmlSerializer, boolean, int)}. That must be
+ * This will NOT call {@link #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. That must be
* handled by the caller.
*/
void migrateState(@NonNull PackageStateInternal oldPkgSetting,
@@ -259,24 +258,24 @@
* Serializes the entire internal state. This is equivalent to a full backup of the existing
* verification state. This write includes legacy state, as a sibling tag the modern state.
*
+ * @param snapshot
* @param includeSignatures Whether to include the package signatures in the output, mainly
* used for backing up the user settings and ensuring they're
* re-attached to the same package.
* @param userId The user to write out. Supports {@link UserHandle#USER_ALL} if all users
- * should be written.
*/
- void writeSettings(@NonNull TypedXmlSerializer serializer, boolean includeSignatures,
- @UserIdInt int userId) throws IOException;
+ void writeSettings(@NonNull Computer snapshot, @NonNull TypedXmlSerializer serializer,
+ boolean includeSignatures, @UserIdInt int userId) throws IOException;
/**
* Read back a list of {@link DomainVerificationPkgState}s previously written by {@link
- * #writeSettings(TypedXmlSerializer, boolean, int)}. Assumes that the
+ * #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. Assumes that the
* {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS} tag has already been entered.
* <p>
* This is expected to only be used to re-attach states for packages already known to be on the
- * device. If restoring from a backup, use {@link #restoreSettings(TypedXmlPullParser)}.
+ * device. If restoring from a backup, use {@link #restoreSettings(Computer, TypedXmlPullParser)}.
*/
- void readSettings(@NonNull TypedXmlPullParser parser)
+ void readSettings(@NonNull Computer snapshot, @NonNull TypedXmlPullParser parser)
throws IOException, XmlPullParserException;
/**
@@ -306,7 +305,7 @@
/**
* Restore a list of {@link DomainVerificationPkgState}s previously written by {@link
- * #writeSettings(TypedXmlSerializer, boolean, int)}. Assumes that the
+ * #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. Assumes that the
* {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS}
* tag has already been entered.
* <p>
@@ -321,7 +320,7 @@
* TODO(b/170746586): Figure out how to verify that package signatures match at snapshot time
* and restore time.
*/
- void restoreSettings(@NonNull TypedXmlPullParser parser)
+ void restoreSettings(@NonNull Computer snapshot, @NonNull TypedXmlPullParser parser)
throws IOException, XmlPullParserException;
/**
@@ -349,17 +348,14 @@
/**
* Print the verification state and user selection state of a package.
*
+ * @param snapshot
* @param packageName the package whose state to change, or all packages if none is
* specified
* @param userId the specific user to print, or null to skip printing user selection
- * states, supports {@link android.os.UserHandle#USER_ALL}
- * @param pkgSettingFunction the method by which to retrieve package data; if this is called
- * from {@link PackageManagerService}, it is expected to pass in the
- * snapshot of {@link PackageStateInternal} objects
+ * states, supports {@link UserHandle#USER_ALL}
*/
- void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName,
- @Nullable @UserIdInt Integer userId,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction)
+ void printState(@NonNull Computer snapshot, @NonNull IndentingPrintWriter writer,
+ @Nullable String packageName, @Nullable @UserIdInt Integer userId)
throws NameNotFoundException;
@NonNull
@@ -406,12 +402,11 @@
@NonNull Set<String> domains, int state) throws NameNotFoundException;
- interface Connection extends DomainVerificationEnforcer.Callback,
- PackageSettingsSnapshotProvider {
+ interface Connection extends DomainVerificationEnforcer.Callback {
/**
* Notify that a settings change has been made and that eventually
- * {@link #writeSettings(TypedXmlSerializer, boolean, int)} should be invoked by the parent.
+ * {@link #writeSettings(Computer, TypedXmlSerializer, boolean, int)} should be invoked by the parent.
*/
void scheduleWriteSettings();
@@ -433,5 +428,8 @@
@UserIdInt
int[] getAllUserIds();
+
+ @NonNull
+ Computer snapshot();
}
}
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 d6c89f7..13218ea 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
@@ -37,7 +37,6 @@
import android.content.pm.verify.domain.DomainVerificationState;
import android.content.pm.verify.domain.DomainVerificationUserState;
import android.content.pm.verify.domain.IDomainVerificationManager;
-import android.os.Build;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -52,11 +51,10 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.FunctionalUtils;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.compat.PlatformCompat;
-import com.android.server.pm.Settings;
+import com.android.server.pm.Computer;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
@@ -80,7 +78,6 @@
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
-import java.util.function.Consumer;
import java.util.function.Function;
@SuppressLint("MissingPermission")
@@ -109,9 +106,9 @@
* immediately attached once its available.
* <p>
* Generally this should be not accessed directly. Prefer calling {@link
- * #getAndValidateAttachedLocked(UUID, Set, boolean, int, Integer, Function)}.
+ * #getAndValidateAttachedLocked(UUID, Set, boolean, int, Integer, Computer)}.
*
- * @see #getAndValidateAttachedLocked(UUID, Set, boolean, int, Integer, Function)
+ * @see #getAndValidateAttachedLocked(UUID, Set, boolean, int, Integer, Computer)
**/
@GuardedBy("mLock")
@NonNull
@@ -178,12 +175,7 @@
@Override
public void setConnection(@NonNull Connection connection) {
- if (Build.IS_USERDEBUG || Build.IS_ENG) {
- mConnection = new LockSafeConnection(connection);
- } else {
- mConnection = connection;
- }
-
+ mConnection = connection;
mEnforcer.setCallback(mConnection);
}
@@ -264,44 +256,43 @@
public DomainVerificationInfo getDomainVerificationInfo(@NonNull String packageName)
throws NameNotFoundException {
mEnforcer.assertApprovedQuerent(mConnection.getCallingUid(), mProxy);
- return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> {
- synchronized (mLock) {
- PackageStateInternal pkgSetting = pkgSettings.apply(packageName);
- AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
- if (pkg == null) {
- throw DomainVerificationUtils.throwPackageUnavailable(packageName);
- }
-
- DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
- if (pkgState == null) {
- return null;
- }
-
- ArrayMap<String, Integer> hostToStateMap = new ArrayMap<>(pkgState.getStateMap());
-
- // TODO(b/159952358): Should the domain list be cached?
- ArraySet<String> domains = mCollector.collectValidAutoVerifyDomains(pkg);
- if (domains.isEmpty()) {
- return null;
- }
-
- int size = domains.size();
- for (int index = 0; index < size; index++) {
- hostToStateMap.putIfAbsent(domains.valueAt(index),
- DomainVerificationState.STATE_NO_RESPONSE);
- }
-
- final int mapSize = hostToStateMap.size();
- for (int index = 0; index < mapSize; index++) {
- int internalValue = hostToStateMap.valueAt(index);
- int publicValue = DomainVerificationState.convertToInfoState(internalValue);
- hostToStateMap.setValueAt(index, publicValue);
- }
-
- // TODO(b/159952358): Do not return if no values are editable (all ignored states)?
- return new DomainVerificationInfo(pkgState.getId(), packageName, hostToStateMap);
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName);
+ AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
+ if (pkg == null) {
+ throw DomainVerificationUtils.throwPackageUnavailable(packageName);
}
- });
+
+ DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
+ if (pkgState == null) {
+ return null;
+ }
+
+ ArrayMap<String, Integer> hostToStateMap = new ArrayMap<>(pkgState.getStateMap());
+
+ // TODO(b/159952358): Should the domain list be cached?
+ ArraySet<String> domains = mCollector.collectValidAutoVerifyDomains(pkg);
+ if (domains.isEmpty()) {
+ return null;
+ }
+
+ int size = domains.size();
+ for (int index = 0; index < size; index++) {
+ hostToStateMap.putIfAbsent(domains.valueAt(index),
+ DomainVerificationState.STATE_NO_RESPONSE);
+ }
+
+ final int mapSize = hostToStateMap.size();
+ for (int index = 0; index < mapSize; index++) {
+ int internalValue = hostToStateMap.valueAt(index);
+ int publicValue = DomainVerificationState.convertToInfoState(internalValue);
+ hostToStateMap.setValueAt(index, publicValue);
+ }
+
+ // TODO(b/159952358): Do not return if no values are editable (all ignored states)?
+ return new DomainVerificationInfo(pkgState.getId(), packageName, hostToStateMap);
+ }
}
@DomainVerificationManager.Error
@@ -324,42 +315,40 @@
@NonNull Set<String> domains, int state)
throws NameNotFoundException {
mEnforcer.assertApprovedVerifier(callingUid, mProxy);
- return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> {
- synchronized (mLock) {
- List<String> verifiedDomains = new ArrayList<>();
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ List<String> verifiedDomains = new ArrayList<>();
- GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains,
- true /* forAutoVerify */, callingUid, null /* userId */,
- pkgSettings);
- if (result.isError()) {
- return result.getErrorCode();
- }
-
- DomainVerificationPkgState pkgState = result.getPkgState();
- ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
- for (String domain : domains) {
- Integer previousState = stateMap.get(domain);
- if (previousState != null
- && !DomainVerificationState.isModifiable(previousState)) {
- continue;
- }
-
- if (DomainVerificationState.isVerified(state)) {
- verifiedDomains.add(domain);
- }
-
- stateMap.put(domain, state);
- }
-
- int size = verifiedDomains.size();
- for (int index = 0; index < size; index++) {
- removeUserStatesForDomain(verifiedDomains.get(index));
- }
+ GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains,
+ true /* forAutoVerify */, callingUid, null /* userId */, snapshot);
+ if (result.isError()) {
+ return result.getErrorCode();
}
- mConnection.scheduleWriteSettings();
- return DomainVerificationManager.STATUS_OK;
- });
+ DomainVerificationPkgState pkgState = result.getPkgState();
+ ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
+ for (String domain : domains) {
+ Integer previousState = stateMap.get(domain);
+ if (previousState != null
+ && !DomainVerificationState.isModifiable(previousState)) {
+ continue;
+ }
+
+ if (DomainVerificationState.isVerified(state)) {
+ verifiedDomains.add(domain);
+ }
+
+ stateMap.put(domain, state);
+ }
+
+ int size = verifiedDomains.size();
+ for (int index = 0; index < size; index++) {
+ removeUserStatesForDomain(verifiedDomains.get(index));
+ }
+ }
+
+ mConnection.scheduleWriteSettings();
+ return DomainVerificationManager.STATUS_OK;
}
@Override
@@ -380,60 +369,30 @@
ArraySet<String> verifiedDomains = new ArraySet<>();
if (packageName == null) {
- mConnection.withPackageSettingsSnapshot(pkgSettings -> {
- synchronized (mLock) {
- ArraySet<String> validDomains = new ArraySet<>();
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ ArraySet<String> validDomains = new ArraySet<>();
- int size = mAttachedPkgStates.size();
- for (int index = 0; index < size; index++) {
- DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
- String pkgName = pkgState.getPackageName();
- PackageStateInternal pkgSetting = pkgSettings.apply(pkgName);
- if (pkgSetting == null || pkgSetting.getPkg() == null) {
- continue;
- }
-
- AndroidPackage pkg = pkgSetting.getPkg();
-
- validDomains.clear();
-
- ArraySet<String> autoVerifyDomains =
- mCollector.collectValidAutoVerifyDomains(pkg);
- if (domains == null) {
- validDomains.addAll(autoVerifyDomains);
- } else {
- validDomains.addAll(domains);
- validDomains.retainAll(autoVerifyDomains);
- }
-
- if (DomainVerificationState.isVerified(state)) {
- verifiedDomains.addAll(validDomains);
- }
-
- setDomainVerificationStatusInternal(pkgState, state, validDomains);
- }
- }
- });
- } else {
- mConnection.withPackageSettingsSnapshotThrowing(pkgSettings -> {
- synchronized (mLock) {
- DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
- if (pkgState == null) {
- throw DomainVerificationUtils.throwPackageUnavailable(packageName);
- }
-
- PackageStateInternal pkgSetting = pkgSettings.apply(packageName);
+ int size = mAttachedPkgStates.size();
+ for (int index = 0; index < size; index++) {
+ DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
+ String pkgName = pkgState.getPackageName();
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName);
if (pkgSetting == null || pkgSetting.getPkg() == null) {
- throw DomainVerificationUtils.throwPackageUnavailable(packageName);
+ continue;
}
AndroidPackage pkg = pkgSetting.getPkg();
- final ArraySet<String> validDomains;
+
+ validDomains.clear();
+
+ ArraySet<String> autoVerifyDomains =
+ mCollector.collectValidAutoVerifyDomains(pkg);
if (domains == null) {
- validDomains = mCollector.collectValidAutoVerifyDomains(pkg);
+ validDomains.addAll(autoVerifyDomains);
} else {
- validDomains = domains;
- validDomains.retainAll(mCollector.collectValidAutoVerifyDomains(pkg));
+ validDomains.addAll(domains);
+ validDomains.retainAll(autoVerifyDomains);
}
if (DomainVerificationState.isVerified(state)) {
@@ -442,7 +401,35 @@
setDomainVerificationStatusInternal(pkgState, state, validDomains);
}
- });
+ }
+ } else {
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
+ if (pkgState == null) {
+ throw DomainVerificationUtils.throwPackageUnavailable(packageName);
+ }
+
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName);
+ if (pkgSetting == null || pkgSetting.getPkg() == null) {
+ throw DomainVerificationUtils.throwPackageUnavailable(packageName);
+ }
+
+ AndroidPackage pkg = pkgSetting.getPkg();
+ final ArraySet<String> validDomains;
+ if (domains == null) {
+ validDomains = mCollector.collectValidAutoVerifyDomains(pkg);
+ } else {
+ validDomains = domains;
+ validDomains.retainAll(mCollector.collectValidAutoVerifyDomains(pkg));
+ }
+
+ if (DomainVerificationState.isVerified(state)) {
+ verifiedDomains.addAll(validDomains);
+ }
+
+ setDomainVerificationStatusInternal(pkgState, state, validDomains);
+ }
}
// Mirror SystemApi behavior of revoking user selection for approved domains.
@@ -552,39 +539,38 @@
return DomainVerificationManager.ERROR_DOMAIN_SET_ID_INVALID;
}
- return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> {
- synchronized (mLock) {
- GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains,
- false /* forAutoVerify */, callingUid, userId, pkgSettings);
- if (result.isError()) {
- return result.getErrorCode();
- }
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ GetAttachedResult result = getAndValidateAttachedLocked(domainSetId, domains,
+ false /* forAutoVerify */, callingUid, userId, snapshot);
+ if (result.isError()) {
+ return result.getErrorCode();
+ }
- DomainVerificationPkgState pkgState = result.getPkgState();
- DomainVerificationInternalUserState userState = pkgState.getOrCreateUserState(
- userId);
+ DomainVerificationPkgState pkgState = result.getPkgState();
+ DomainVerificationInternalUserState userState = pkgState.getOrCreateUserState(
+ userId);
- // Disable other packages if approving this one. Note that this check is only done
- // for enabling. This allows an escape hatch in case multiple packages somehow get
- // selected. They can be disabled without blocking in a circular dependency.
- if (enabled) {
- int statusCode = revokeOtherUserSelectionsLocked(userState, userId, domains,
- pkgSettings);
- if (statusCode != DomainVerificationManager.STATUS_OK) {
- return statusCode;
- }
- }
-
- if (enabled) {
- userState.addHosts(domains);
- } else {
- userState.removeHosts(domains);
+ // Disable other packages if approving this one. Note that this check is only done
+ // for enabling. This allows an escape hatch in case multiple packages somehow get
+ // selected. They can be disabled without blocking in a circular dependency.
+ if (enabled) {
+ int statusCode = revokeOtherUserSelectionsLocked(userState, userId, domains,
+ snapshot);
+ if (statusCode != DomainVerificationManager.STATUS_OK) {
+ return statusCode;
}
}
- mConnection.scheduleWriteSettings();
- return DomainVerificationManager.STATUS_OK;
- });
+ if (enabled) {
+ userState.addHosts(domains);
+ } else {
+ userState.removeHosts(domains);
+ }
+ }
+
+ mConnection.scheduleWriteSettings();
+ return DomainVerificationManager.STATUS_OK;
}
@Override
@@ -592,48 +578,47 @@
@NonNull String packageName, boolean enabled, @Nullable ArraySet<String> domains)
throws NameNotFoundException {
mEnforcer.assertInternal(mConnection.getCallingUid());
- mConnection.withPackageSettingsSnapshotThrowing(pkgSettings -> {
- synchronized (mLock) {
- DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
- if (pkgState == null) {
- throw DomainVerificationUtils.throwPackageUnavailable(packageName);
- }
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
+ if (pkgState == null) {
+ throw DomainVerificationUtils.throwPackageUnavailable(packageName);
+ }
- PackageStateInternal pkgSetting = pkgSettings.apply(packageName);
- AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
- if (pkg == null) {
- throw DomainVerificationUtils.throwPackageUnavailable(packageName);
- }
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName);
+ AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
+ if (pkg == null) {
+ throw DomainVerificationUtils.throwPackageUnavailable(packageName);
+ }
- Set<String> validDomains =
- domains == null ? mCollector.collectAllWebDomains(pkg) : domains;
+ Set<String> validDomains =
+ domains == null ? mCollector.collectAllWebDomains(pkg) : domains;
- validDomains.retainAll(mCollector.collectAllWebDomains(pkg));
+ validDomains.retainAll(mCollector.collectAllWebDomains(pkg));
- if (userId == UserHandle.USER_ALL) {
- for (int aUserId : mConnection.getAllUserIds()) {
- DomainVerificationInternalUserState userState =
- pkgState.getOrCreateUserState(aUserId);
- revokeOtherUserSelectionsLocked(userState, aUserId, validDomains,
- pkgSettings);
- if (enabled) {
- userState.addHosts(validDomains);
- } else {
- userState.removeHosts(validDomains);
- }
- }
- } else {
+ if (userId == UserHandle.USER_ALL) {
+ for (int aUserId : mConnection.getAllUserIds()) {
DomainVerificationInternalUserState userState =
- pkgState.getOrCreateUserState(userId);
- revokeOtherUserSelectionsLocked(userState, userId, validDomains, pkgSettings);
+ pkgState.getOrCreateUserState(aUserId);
+ revokeOtherUserSelectionsLocked(userState, aUserId, validDomains,
+ snapshot);
if (enabled) {
userState.addHosts(validDomains);
} else {
userState.removeHosts(validDomains);
}
}
+ } else {
+ DomainVerificationInternalUserState userState =
+ pkgState.getOrCreateUserState(userId);
+ revokeOtherUserSelectionsLocked(userState, userId, validDomains, snapshot);
+ if (enabled) {
+ userState.addHosts(validDomains);
+ } else {
+ userState.removeHosts(validDomains);
+ }
}
- });
+ }
mConnection.scheduleWriteSettings();
}
@@ -641,8 +626,7 @@
@GuardedBy("mLock")
private int revokeOtherUserSelectionsLocked(
@NonNull DomainVerificationInternalUserState userState, @UserIdInt int userId,
- @NonNull Set<String> domains,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction) {
+ @NonNull Set<String> domains, @NonNull Computer snapshot) {
// Cache the approved packages from the 1st pass because the search is expensive
ArrayMap<String, List<String>> domainToApprovedPackages = new ArrayMap<>();
@@ -652,7 +636,7 @@
}
Pair<List<String>, Integer> packagesToLevel = getApprovedPackagesLocked(domain,
- userId, APPROVAL_LEVEL_NONE + 1, pkgSettingFunction);
+ userId, APPROVAL_LEVEL_NONE + 1, snapshot);
int highestApproval = packagesToLevel.second;
if (highestApproval > APPROVAL_LEVEL_SELECTION) {
return DomainVerificationManager.ERROR_UNABLE_TO_APPROVE;
@@ -698,51 +682,50 @@
throw DomainVerificationUtils.throwPackageUnavailable(packageName);
}
- return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> {
- synchronized (mLock) {
- PackageStateInternal pkgSetting = pkgSettings.apply(packageName);
- AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
- if (pkg == null) {
- throw DomainVerificationUtils.throwPackageUnavailable(packageName);
- }
-
- DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
- if (pkgState == null) {
- return null;
- }
-
- ArraySet<String> webDomains = mCollector.collectAllWebDomains(pkg);
- int webDomainsSize = webDomains.size();
-
- Map<String, Integer> domains = new ArrayMap<>(webDomainsSize);
- ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
- DomainVerificationInternalUserState userState = pkgState.getUserState(userId);
- Set<String> enabledHosts =
- userState == null ? emptySet() : userState.getEnabledHosts();
-
- for (int index = 0; index < webDomainsSize; index++) {
- String host = webDomains.valueAt(index);
- Integer state = stateMap.get(host);
-
- int domainState;
- if (state != null && DomainVerificationState.isVerified(state)) {
- domainState = DomainVerificationUserState.DOMAIN_STATE_VERIFIED;
- } else if (enabledHosts.contains(host)) {
- domainState = DomainVerificationUserState.DOMAIN_STATE_SELECTED;
- } else {
- domainState = DomainVerificationUserState.DOMAIN_STATE_NONE;
- }
-
- domains.put(host, domainState);
- }
-
- boolean linkHandlingAllowed =
- userState == null || userState.isLinkHandlingAllowed();
-
- return new DomainVerificationUserState(pkgState.getId(), packageName,
- UserHandle.of(userId), linkHandlingAllowed, domains);
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName);
+ AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
+ if (pkg == null) {
+ throw DomainVerificationUtils.throwPackageUnavailable(packageName);
}
- });
+
+ DomainVerificationPkgState pkgState = mAttachedPkgStates.get(packageName);
+ if (pkgState == null) {
+ return null;
+ }
+
+ ArraySet<String> webDomains = mCollector.collectAllWebDomains(pkg);
+ int webDomainsSize = webDomains.size();
+
+ Map<String, Integer> domains = new ArrayMap<>(webDomainsSize);
+ ArrayMap<String, Integer> stateMap = pkgState.getStateMap();
+ DomainVerificationInternalUserState userState = pkgState.getUserState(userId);
+ Set<String> enabledHosts =
+ userState == null ? emptySet() : userState.getEnabledHosts();
+
+ for (int index = 0; index < webDomainsSize; index++) {
+ String host = webDomains.valueAt(index);
+ Integer state = stateMap.get(host);
+
+ int domainState;
+ if (state != null && DomainVerificationState.isVerified(state)) {
+ domainState = DomainVerificationUserState.DOMAIN_STATE_VERIFIED;
+ } else if (enabledHosts.contains(host)) {
+ domainState = DomainVerificationUserState.DOMAIN_STATE_SELECTED;
+ } else {
+ domainState = DomainVerificationUserState.DOMAIN_STATE_NONE;
+ }
+
+ domains.put(host, domainState);
+ }
+
+ boolean linkHandlingAllowed =
+ userState == null || userState.isLinkHandlingAllowed();
+
+ return new DomainVerificationUserState(pkgState.getId(), packageName,
+ UserHandle.of(userId), linkHandlingAllowed, domains);
+ }
}
@NonNull
@@ -751,27 +734,26 @@
mEnforcer.assertOwnerQuerent(mConnection.getCallingUid(), mConnection.getCallingUserId(),
userId);
- return mConnection.withPackageSettingsSnapshotReturningThrowing(pkgSettings -> {
- SparseArray<List<String>> levelToPackages = getOwnersForDomainInternal(domain, false,
- userId, pkgSettings);
- if (levelToPackages.size() == 0) {
- return emptyList();
- }
+ final Computer snapshot = mConnection.snapshot();
+ SparseArray<List<String>> levelToPackages = getOwnersForDomainInternal(domain, false,
+ userId, snapshot);
+ if (levelToPackages.size() == 0) {
+ return emptyList();
+ }
- List<DomainOwner> owners = new ArrayList<>();
- int size = levelToPackages.size();
- for (int index = 0; index < size; index++) {
- int level = levelToPackages.keyAt(index);
- boolean overrideable = level <= APPROVAL_LEVEL_SELECTION;
- List<String> packages = levelToPackages.valueAt(index);
- int packagesSize = packages.size();
- for (int packageIndex = 0; packageIndex < packagesSize; packageIndex++) {
- owners.add(new DomainOwner(packages.get(packageIndex), overrideable));
- }
+ List<DomainOwner> owners = new ArrayList<>();
+ int size = levelToPackages.size();
+ for (int index = 0; index < size; index++) {
+ int level = levelToPackages.keyAt(index);
+ boolean overrideable = level <= APPROVAL_LEVEL_SELECTION;
+ List<String> packages = levelToPackages.valueAt(index);
+ int packagesSize = packages.size();
+ for (int packageIndex = 0; packageIndex < packagesSize; packageIndex++) {
+ owners.add(new DomainOwner(packages.get(packageIndex), overrideable));
}
+ }
- return owners;
- });
+ return owners;
}
/**
@@ -782,8 +764,7 @@
*/
@NonNull
private SparseArray<List<String>> getOwnersForDomainInternal(@NonNull String domain,
- boolean includeNegative, @UserIdInt int userId,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction) {
+ boolean includeNegative, @UserIdInt int userId, @NonNull Computer snapshot) {
SparseArray<List<String>> levelToPackages = new SparseArray<>();
// First, collect the raw approval level values
synchronized (mLock) {
@@ -791,7 +772,7 @@
for (int index = 0; index < size; index++) {
DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
String packageName = pkgState.getPackageName();
- PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName);
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName);
if (pkgSetting == null) {
continue;
}
@@ -818,8 +799,8 @@
// Then sort them ascending by first installed time, with package name as tie breaker
for (int index = 0; index < size; index++) {
levelToPackages.valueAt(index).sort((first, second) -> {
- PackageStateInternal firstPkgSetting = pkgSettingFunction.apply(first);
- PackageStateInternal secondPkgSetting = pkgSettingFunction.apply(second);
+ PackageStateInternal firstPkgSetting = snapshot.getPackageStateInternal(first);
+ PackageStateInternal secondPkgSetting = snapshot.getPackageStateInternal(second);
long firstInstallTime = firstPkgSetting == null
? -1L : firstPkgSetting.getUserStateOrDefault(userId).getFirstInstallTime();
@@ -1060,44 +1041,38 @@
}
@Override
- public void writeSettings(@NonNull TypedXmlSerializer serializer, boolean includeSignatures,
- @UserIdInt int userId)
- throws IOException {
- mConnection.withPackageSettingsSnapshotThrowing(pkgSettings -> {
- synchronized (mLock) {
- Function<String, String> pkgNameToSignature = null;
- if (includeSignatures) {
- pkgNameToSignature = pkgName -> {
- PackageStateInternal pkgSetting = pkgSettings.apply(pkgName);
- if (pkgSetting == null) {
- // If querying for a user restored package that isn't installed on the
- // device yet, there will be no signature to write out. In that case,
- // it's expected that this returns null and it falls back to the
- // restored state's stored signature if it exists.
- return null;
- }
+ public void writeSettings(Computer snapshot, @NonNull TypedXmlSerializer serializer,
+ boolean includeSignatures, @UserIdInt int userId) throws IOException {
+ synchronized (mLock) {
+ Function<String, String> pkgNameToSignature = null;
+ if (includeSignatures) {
+ pkgNameToSignature = pkgName -> {
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName);
+ if (pkgSetting == null) {
+ // If querying for a user restored package that isn't installed on the
+ // device yet, there will be no signature to write out. In that case,
+ // it's expected that this returns null and it falls back to the
+ // restored state's stored signature if it exists.
+ return null;
+ }
- return PackageUtils.computeSignaturesSha256Digest(
- pkgSetting.getSigningDetails().getSignatures());
- };
- }
-
- mSettings.writeSettings(serializer, mAttachedPkgStates, userId, pkgNameToSignature);
+ return PackageUtils.computeSignaturesSha256Digest(
+ pkgSetting.getSigningDetails().getSignatures());
+ };
}
- });
+
+ mSettings.writeSettings(serializer, mAttachedPkgStates, userId, pkgNameToSignature);
+ }
mLegacySettings.writeSettings(serializer);
}
@Override
- public void readSettings(@NonNull TypedXmlPullParser parser) throws IOException,
- XmlPullParserException {
- mConnection.<IOException, XmlPullParserException>withPackageSettingsSnapshotThrowing2(
- pkgSettings -> {
- synchronized (mLock) {
- mSettings.readSettings(parser, mAttachedPkgStates, pkgSettings);
- }
- });
+ public void readSettings(@NonNull Computer snapshot, @NonNull TypedXmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ synchronized (mLock) {
+ mSettings.readSettings(parser, mAttachedPkgStates, snapshot);
+ }
}
@Override
@@ -1107,14 +1082,11 @@
}
@Override
- public void restoreSettings(@NonNull TypedXmlPullParser parser)
+ public void restoreSettings(Computer snapshot, @NonNull TypedXmlPullParser parser)
throws IOException, XmlPullParserException {
- mConnection.<IOException, XmlPullParserException>withPackageSettingsSnapshotThrowing2(
- pkgSettings -> {
- synchronized (mLock) {
- mSettings.restoreSettings(parser, mAttachedPkgStates, pkgSettings);
- }
- });
+ synchronized (mLock) {
+ mSettings.restoreSettings(parser, mAttachedPkgStates, snapshot);
+ }
}
@Override
@@ -1190,18 +1162,16 @@
@Override
public void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName,
@Nullable Integer userId) throws NameNotFoundException {
- mConnection.withPackageSettingsSnapshotThrowing(
- pkgSettings -> printState(writer, packageName, userId, pkgSettings));
+ printState(mConnection.snapshot(), writer, packageName, userId);
}
@Override
- public void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName,
- @Nullable @UserIdInt Integer userId,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction)
+ public void printState(@NonNull Computer snapshot, @NonNull IndentingPrintWriter writer,
+ @Nullable String packageName, @Nullable @UserIdInt Integer userId)
throws NameNotFoundException {
mEnforcer.assertApprovedQuerent(mConnection.getCallingUid(), mProxy);
synchronized (mLock) {
- mDebug.printState(writer, packageName, userId, pkgSettingFunction, mAttachedPkgStates);
+ mDebug.printState(writer, packageName, userId, snapshot, mAttachedPkgStates);
}
}
@@ -1209,31 +1179,30 @@
public void printOwnersForPackage(@NonNull IndentingPrintWriter writer,
@Nullable String packageName, @Nullable @UserIdInt Integer userId)
throws NameNotFoundException {
- mConnection.withPackageSettingsSnapshotThrowing(pkgSettings -> {
- synchronized (mLock) {
- if (packageName == null) {
- int size = mAttachedPkgStates.size();
- for (int index = 0; index < size; index++) {
- try {
- printOwnersForPackage(writer,
- mAttachedPkgStates.valueAt(index).getPackageName(), userId,
- pkgSettings);
- } catch (NameNotFoundException ignored) {
- // When iterating packages, if one doesn't exist somehow, ignore
- }
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ if (packageName == null) {
+ int size = mAttachedPkgStates.size();
+ for (int index = 0; index < size; index++) {
+ try {
+ printOwnersForPackage(writer,
+ mAttachedPkgStates.valueAt(index).getPackageName(), userId,
+ snapshot);
+ } catch (NameNotFoundException ignored) {
+ // When iterating packages, if one doesn't exist somehow, ignore
}
- } else {
- printOwnersForPackage(writer, packageName, userId, pkgSettings);
}
+ } else {
+ printOwnersForPackage(writer, packageName, userId, snapshot);
}
- });
+ }
}
private void printOwnersForPackage(@NonNull IndentingPrintWriter writer,
@NonNull String packageName, @Nullable @UserIdInt Integer userId,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction)
+ @NonNull Computer snapshot)
throws NameNotFoundException {
- PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName);
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName);
AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
if (pkg == null) {
throw DomainVerificationUtils.throwPackageUnavailable(packageName);
@@ -1249,7 +1218,7 @@
writer.increaseIndent();
for (int index = 0; index < size; index++) {
- printOwnersForDomain(writer, domains.valueAt(index), userId, pkgSettingFunction);
+ printOwnersForDomain(writer, domains.valueAt(index), userId, snapshot);
}
writer.decreaseIndent();
@@ -1258,30 +1227,28 @@
@Override
public void printOwnersForDomains(@NonNull IndentingPrintWriter writer,
@NonNull List<String> domains, @Nullable @UserIdInt Integer userId) {
- mConnection.withPackageSettingsSnapshot(pkgSettings -> {
- synchronized (mLock) {
- int size = domains.size();
- for (int index = 0; index < size; index++) {
- printOwnersForDomain(writer, domains.get(index), userId, pkgSettings);
- }
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ int size = domains.size();
+ for (int index = 0; index < size; index++) {
+ printOwnersForDomain(writer, domains.get(index), userId, snapshot);
}
- });
+ }
}
private void printOwnersForDomain(@NonNull IndentingPrintWriter writer, @NonNull String domain,
- @Nullable @UserIdInt Integer userId,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction) {
+ @Nullable @UserIdInt Integer userId, @NonNull Computer snapshot) {
SparseArray<SparseArray<List<String>>> userIdToApprovalLevelToOwners =
new SparseArray<>();
if (userId == null || userId == UserHandle.USER_ALL) {
for (int aUserId : mConnection.getAllUserIds()) {
userIdToApprovalLevelToOwners.put(aUserId,
- getOwnersForDomainInternal(domain, true, aUserId, pkgSettingFunction));
+ getOwnersForDomainInternal(domain, true, aUserId, snapshot));
}
} else {
userIdToApprovalLevelToOwners.put(userId,
- getOwnersForDomainInternal(domain, true, userId, pkgSettingFunction));
+ getOwnersForDomainInternal(domain, true, userId, snapshot));
}
mDebug.printOwners(writer, domain, userIdToApprovalLevelToOwners);
@@ -1330,8 +1297,7 @@
@GuardedBy("mLock")
private GetAttachedResult getAndValidateAttachedLocked(@NonNull UUID domainSetId,
@NonNull Set<String> domains, boolean forAutoVerify, int callingUid,
- @Nullable Integer userIdForFilter,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction)
+ @Nullable Integer userIdForFilter, @NonNull Computer snapshot)
throws NameNotFoundException {
if (domainSetId == null) {
throw new IllegalArgumentException("domainSetId cannot be null");
@@ -1349,7 +1315,7 @@
return GetAttachedResult.error(DomainVerificationManager.ERROR_DOMAIN_SET_ID_INVALID);
}
- PackageStateInternal pkgSetting = pkgSettingFunction.apply(pkgName);
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName);
if (pkgSetting == null || pkgSetting.getPkg() == null) {
throw DomainVerificationUtils.throwPackageUnavailable(pkgName);
}
@@ -1437,33 +1403,32 @@
@Override
public void clearDomainVerificationState(@Nullable List<String> packageNames) {
mEnforcer.assertInternal(mConnection.getCallingUid());
- mConnection.withPackageSettingsSnapshot(pkgSettings -> {
- synchronized (mLock) {
- if (packageNames == null) {
- int size = mAttachedPkgStates.size();
- for (int index = 0; index < size; index++) {
- DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
- String pkgName = pkgState.getPackageName();
- PackageStateInternal pkgSetting = pkgSettings.apply(pkgName);
- if (pkgSetting == null || pkgSetting.getPkg() == null) {
- continue;
- }
- resetDomainState(pkgState.getStateMap(), pkgSetting);
+ synchronized (mLock) {
+ final Computer snapshot = mConnection.snapshot();
+ if (packageNames == null) {
+ int size = mAttachedPkgStates.size();
+ for (int index = 0; index < size; index++) {
+ DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
+ String pkgName = pkgState.getPackageName();
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName);
+ if (pkgSetting == null || pkgSetting.getPkg() == null) {
+ continue;
}
- } else {
- int size = packageNames.size();
- for (int index = 0; index < size; index++) {
- String pkgName = packageNames.get(index);
- DomainVerificationPkgState pkgState = mAttachedPkgStates.get(pkgName);
- PackageStateInternal pkgSetting = pkgSettings.apply(pkgName);
- if (pkgSetting == null || pkgSetting.getPkg() == null) {
- continue;
- }
- resetDomainState(pkgState.getStateMap(), pkgSetting);
+ resetDomainState(pkgState.getStateMap(), pkgSetting);
+ }
+ } else {
+ int size = packageNames.size();
+ for (int index = 0; index < size; index++) {
+ String pkgName = packageNames.get(index);
+ DomainVerificationPkgState pkgState = mAttachedPkgStates.get(pkgName);
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(pkgName);
+ if (pkgSetting == null || pkgSetting.getPkg() == null) {
+ continue;
}
+ resetDomainState(pkgState.getStateMap(), pkgSetting);
}
}
- });
+ }
mConnection.scheduleWriteSettings();
}
@@ -1935,35 +1900,32 @@
@GuardedBy("mLock")
@NonNull
private Pair<List<String>, Integer> getApprovedPackagesLocked(@NonNull String domain,
- @UserIdInt int userId, int minimumApproval,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction) {
+ @UserIdInt int userId, int minimumApproval, @NonNull Computer snapshot) {
boolean includeNegative = minimumApproval < APPROVAL_LEVEL_NONE;
int highestApproval = minimumApproval;
List<String> approvedPackages = emptyList();
- synchronized (mLock) {
- final int size = mAttachedPkgStates.size();
- for (int index = 0; index < size; index++) {
- DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
- String packageName = pkgState.getPackageName();
- PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName);
- if (pkgSetting == null) {
- continue;
- }
+ final int size = mAttachedPkgStates.size();
+ for (int index = 0; index < size; index++) {
+ DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
+ String packageName = pkgState.getPackageName();
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName);
+ if (pkgSetting == null) {
+ continue;
+ }
- int level = approvalLevelForDomain(pkgSetting, domain, includeNegative, userId,
- domain);
- if (level < minimumApproval) {
- continue;
- }
+ int level = approvalLevelForDomain(pkgSetting, domain, includeNegative, userId,
+ domain);
+ if (level < minimumApproval) {
+ continue;
+ }
- if (level > highestApproval) {
- approvedPackages.clear();
- approvedPackages = CollectionUtils.add(approvedPackages, packageName);
- highestApproval = level;
- } else if (level == highestApproval) {
- approvedPackages = CollectionUtils.add(approvedPackages, packageName);
- }
+ if (level > highestApproval) {
+ approvedPackages.clear();
+ approvedPackages = CollectionUtils.add(approvedPackages, packageName);
+ highestApproval = level;
+ } else if (level == highestApproval) {
+ approvedPackages = CollectionUtils.add(approvedPackages, packageName);
}
}
@@ -1976,7 +1938,7 @@
final int approvedSize = approvedPackages.size();
for (int index = 0; index < approvedSize; index++) {
String packageName = approvedPackages.get(index);
- PackageStateInternal pkgSetting = pkgSettingFunction.apply(packageName);
+ PackageStateInternal pkgSetting = snapshot.getPackageStateInternal(packageName);
if (pkgSetting == null) {
continue;
}
@@ -2035,108 +1997,4 @@
return mErrorCode;
}
}
-
- /**
- * Wraps a {@link Connection} to verify that the {@link PackageStateInternal} calls do not hold
- * {@link #mLock}, as that can cause deadlock when {@link Settings} tries to serialize state to
- * disk. Only enabled if {@link Build#IS_USERDEBUG} or {@link Build#IS_ENG} is true.
- */
- private class LockSafeConnection implements Connection {
-
- @NonNull
- private final Connection mConnection;
-
- private LockSafeConnection(@NonNull Connection connection) {
- mConnection = connection;
- }
-
- private void enforceLocking() {
- if (Thread.holdsLock(mLock)) {
- Slog.wtf(TAG, "Method should not hold DVS lock when accessing package data");
- }
- }
-
- @Override
- public void withPackageSettingsSnapshot(
- @NonNull Consumer<Function<String, PackageStateInternal>> block) {
- enforceLocking();
- mConnection.withPackageSettingsSnapshot(block);
- }
-
- @Override
- public <Output> Output withPackageSettingsSnapshotReturning(
- @NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageStateInternal>,
- Output> block) {
- enforceLocking();
- return mConnection.withPackageSettingsSnapshotReturning(block);
- }
-
- @Override
- public <ExceptionType extends Exception> void withPackageSettingsSnapshotThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedConsumer<
- Function<String, PackageStateInternal>, ExceptionType> block)
- throws ExceptionType {
- enforceLocking();
- mConnection.withPackageSettingsSnapshotThrowing(block);
- }
-
- @Override
- public <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
- withPackageSettingsSnapshotThrowing2(
- @NonNull FunctionalUtils.ThrowingChecked2Consumer<
- Function<String, PackageStateInternal>, ExceptionOne,
- ExceptionTwo> block)
- throws ExceptionOne, ExceptionTwo {
- enforceLocking();
- mConnection.withPackageSettingsSnapshotThrowing2(block);
- }
-
- @Override
- public <Output, ExceptionType extends Exception> Output
- withPackageSettingsSnapshotReturningThrowing(
- @NonNull FunctionalUtils.ThrowingCheckedFunction<
- Function<String, PackageStateInternal>, Output,
- ExceptionType> block)
- throws ExceptionType {
- enforceLocking();
- return mConnection.withPackageSettingsSnapshotReturningThrowing(block);
- }
-
- @Override
- public void scheduleWriteSettings() {
- mConnection.scheduleWriteSettings();
- }
-
- @Override
- public int getCallingUid() {
- return mConnection.getCallingUid();
- }
-
- @Override
- @UserIdInt
- public int getCallingUserId() {
- return mConnection.getCallingUserId();
- }
-
- @Override
- public void schedule(int code, @Nullable Object object) {
- mConnection.schedule(code, object);
- }
-
- @Override
- @UserIdInt
- public int[] getAllUserIds() {
- return mConnection.getAllUserIds();
- }
-
- @Override
- public boolean filterAppAccess(@NonNull String packageName, int callingUid, int userId) {
- return mConnection.filterAppAccess(packageName, callingUid, userId);
- }
-
- @Override
- public boolean doesUserExist(int userId) {
- return mConnection.doesUserExist(userId);
- }
- }
}
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java
index 015d4e9..8d1ae0b 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationSettings.java
@@ -28,6 +28,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.Computer;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState;
@@ -101,8 +102,7 @@
*/
public void readSettings(@NonNull TypedXmlPullParser parser,
@NonNull DomainVerificationStateMap<DomainVerificationPkgState> liveState,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction)
- throws IOException, XmlPullParserException {
+ @NonNull Computer snapshot) throws IOException, XmlPullParserException {
DomainVerificationPersistence.ReadResult result =
DomainVerificationPersistence.readFromXml(parser);
ArrayMap<String, DomainVerificationPkgState> active = result.active;
@@ -118,7 +118,7 @@
// This branch should never be possible. Settings should be read from disk
// before any states are attached. But just in case, handle it.
if (!existingState.getId().equals(pkgState.getId())) {
- mergePkgState(existingState, pkgState, pkgSettingFunction);
+ mergePkgState(existingState, pkgState, snapshot);
}
} else {
mPendingPkgStates.put(pkgName, pkgState);
@@ -139,8 +139,7 @@
*/
public void restoreSettings(@NonNull TypedXmlPullParser parser,
@NonNull DomainVerificationStateMap<DomainVerificationPkgState> liveState,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction)
- throws IOException, XmlPullParserException {
+ @NonNull Computer snapshot) throws IOException, XmlPullParserException {
// TODO(b/170746586): Restoration assumes user IDs match, which is probably not the case on
// a new device.
@@ -166,7 +165,7 @@
}
if (existingState != null) {
- mergePkgState(existingState, newState, pkgSettingFunction);
+ mergePkgState(existingState, newState, snapshot);
} else {
// If there's no existing state, that means the new state has to be transformed
// in preparation for attaching to brand new package that may eventually be
@@ -216,9 +215,9 @@
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public void mergePkgState(@NonNull DomainVerificationPkgState oldState,
- @NonNull DomainVerificationPkgState newState,
- @NonNull Function<String, PackageStateInternal> pkgSettingFunction) {
- PackageStateInternal pkgSetting = pkgSettingFunction.apply(oldState.getPackageName());
+ @NonNull DomainVerificationPkgState newState, @NonNull Computer snapshot) {
+ PackageStateInternal pkgSetting =
+ snapshot.getPackageStateInternal(oldState.getPackageName());
AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
Set<String> validDomains = pkg == null
? Collections.emptySet() : mCollector.collectValidAutoVerifyDomains(pkg);
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java
index da2d162..4b0a8e2 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java
@@ -32,6 +32,7 @@
import android.util.IndentingPrintWriter;
import com.android.modules.utils.BasicShellCommandHandler;
+import com.android.server.pm.Computer;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -39,7 +40,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Locale;
-import java.util.function.Function;
public class DomainVerificationShell {
@@ -599,8 +599,8 @@
void verifyPackages(@Nullable List<String> packageNames, boolean reVerify);
/**
- * @see DomainVerificationManagerInternal#printState(IndentingPrintWriter, String, Integer,
- * Function)
+ * @see DomainVerificationManagerInternal#printState(Computer, IndentingPrintWriter, String,
+ * Integer)
*/
void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName,
@Nullable @UserIdInt Integer userId) throws NameNotFoundException;
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index 43b2e1e..dcc461b 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -265,12 +265,14 @@
assertServiceInitialized() ?: return
when (params.result) {
is Result.Changed, Result.ChangedWithoutNotify -> {
- assertThat(mockPendingBroadcasts.get(userId, params.pkgName) ?: emptyList<String>())
+ assertThat(mockPendingBroadcasts.copiedMap()?.get(userId)?.get(params.pkgName)
+ ?: emptyList<String>())
.containsExactly(params.componentName!!.className)
.inOrder()
}
is Result.NotChanged, is Result.Exception -> {
- assertThat(mockPendingBroadcasts.get(userId, params.pkgName)).isNull()
+ assertThat(mockPendingBroadcasts.copiedMap()?.get(userId)?.get(params.pkgName))
+ .isNull()
}
}.run { /*exhaust*/ }
}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
index 92cdb34..c9601de 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
@@ -20,8 +20,6 @@
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.SigningDetails
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
import android.content.pm.verify.domain.DomainVerificationManager
import android.content.pm.verify.domain.DomainVerificationState
import android.os.Build
@@ -30,10 +28,12 @@
import android.util.IndentingPrintWriter
import android.util.SparseArray
import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.pm.Computer
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
import com.android.server.pm.pkg.PackageUserStateInternal
-import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates
+import com.android.server.pm.pkg.component.ParsedActivityImpl
+import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
import com.android.server.pm.verify.domain.DomainVerificationEnforcer
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
import com.android.server.pm.verify.domain.DomainVerificationService
@@ -100,11 +100,15 @@
mockThrowOnUnmocked {
whenever(callingUid) { callingUidInt.get() }
whenever(callingUserId) { callingUserIdInt.get() }
- mockPackageStates {
- when (it) {
- VISIBLE_PKG -> visiblePkgState
- INVISIBLE_PKG -> invisiblePkgState
- else -> null
+ whenever(snapshot()) {
+ mockThrowOnUnmocked {
+ whenever(getPackageStateInternal(anyString())) {
+ when (getArgument<String>(0)) {
+ VISIBLE_PKG -> visiblePkgState
+ INVISIBLE_PKG -> invisiblePkgState
+ else -> null
+ }
+ }
}
}
whenever(schedule(anyInt(), any()))
@@ -211,9 +215,8 @@
printState(mock(IndentingPrintWriter::class.java), null, null)
},
service(Type.QUERENT, "printStateInternal") {
- printState(mock(IndentingPrintWriter::class.java), null, null) {
- mockPkgState(it, UUID.randomUUID())
- }
+ printState(mock(Computer::class.java), mock(IndentingPrintWriter::class.java),
+ null, null)
},
service(Type.VERIFIER, "setStatus") {
setDomainVerificationStatus(
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
index 878bee0..7273b0b 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
@@ -19,9 +19,6 @@
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
-import com.android.server.pm.pkg.PackageUserStateInternal
import android.content.pm.verify.domain.DomainOwner
import android.content.pm.verify.domain.DomainVerificationInfo
import android.content.pm.verify.domain.DomainVerificationManager
@@ -34,7 +31,9 @@
import android.util.SparseArray
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
-import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates
+import com.android.server.pm.pkg.PackageUserStateInternal
+import com.android.server.pm.pkg.component.ParsedActivityImpl
+import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
import com.android.server.pm.verify.domain.DomainVerificationManagerStub
import com.android.server.pm.verify.domain.DomainVerificationService
import com.android.server.testutils.mockThrowOnUnmocked
@@ -502,8 +501,12 @@
whenever(callingUid) { Process.ROOT_UID }
whenever(callingUserId) { 0 }
- mockPackageStates {
- pkgStateFunction(it)
+ whenever(snapshot()) {
+ mockThrowOnUnmocked {
+ whenever(getPackageStateInternal(anyString())) {
+ pkgStateFunction(getArgument(0))
+ }
+ }
}
})
}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
index 0369bab..40f37a7 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
@@ -20,9 +20,6 @@
import android.content.pm.PackageManager
import android.content.pm.Signature
import android.content.pm.SigningDetails
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
-import com.android.server.pm.pkg.PackageUserStateInternal
import android.content.pm.verify.domain.DomainOwner
import android.content.pm.verify.domain.DomainVerificationInfo.STATE_MODIFIABLE_VERIFIED
import android.content.pm.verify.domain.DomainVerificationInfo.STATE_NO_RESPONSE
@@ -39,9 +36,12 @@
import android.util.ArraySet
import android.util.SparseArray
import android.util.Xml
+import com.android.server.pm.Computer
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
-import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates
+import com.android.server.pm.pkg.PackageUserStateInternal
+import com.android.server.pm.pkg.component.ParsedActivityImpl
+import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
import com.android.server.pm.verify.domain.DomainVerificationService
import com.android.server.testutils.mock
import com.android.server.testutils.mockThrowOnUnmocked
@@ -194,7 +194,8 @@
"""
val service = makeService(pkg1, pkg2)
- service.restoreSettings(Xml.resolvePullParser(xml.byteInputStream()))
+ val computer = mockComputer(pkg1, pkg2)
+ service.restoreSettings(computer, Xml.resolvePullParser(xml.byteInputStream()))
service.addPackage(pkg1)
val info = service.getInfo(pkg1.packageName)
assertThat(info.packageName).isEqualTo(pkg1.packageName)
@@ -243,7 +244,8 @@
"""
val service = makeService(pkg1, pkg2)
- service.restoreSettings(Xml.resolvePullParser(xml.byteInputStream()))
+ val computer = mockComputer(pkg1, pkg2)
+ service.restoreSettings(computer, Xml.resolvePullParser(xml.byteInputStream()))
service.addPackage(pkg1)
val info = service.getInfo(pkg1.packageName)
assertThat(info.packageName).isEqualTo(pkg1.packageName)
@@ -298,8 +300,9 @@
""".trimIndent()
val service = makeService(pkg1, pkg2)
+ val computer = mockComputer(pkg1, pkg2)
xml.byteInputStream().use {
- service.readSettings(Xml.resolvePullParser(it))
+ service.readSettings(computer, Xml.resolvePullParser(it))
}
service.addPackage(pkg1)
@@ -311,8 +314,9 @@
fun addPackagePendingStripInvalidDomains() {
val xml = addPackagePendingOrRestoredWithInvalidDomains()
val service = makeService(pkg1, pkg2)
+ val computer = mockComputer(pkg1, pkg2)
xml.byteInputStream().use {
- service.readSettings(Xml.resolvePullParser(it))
+ service.readSettings(computer, Xml.resolvePullParser(it))
}
service.addPackage(pkg1)
@@ -334,8 +338,9 @@
fun addPackageRestoredStripInvalidDomains() {
val xml = addPackagePendingOrRestoredWithInvalidDomains()
val service = makeService(pkg1, pkg2)
+ val computer = mockComputer(pkg1, pkg2)
xml.byteInputStream().use {
- service.restoreSettings(Xml.resolvePullParser(it))
+ service.restoreSettings(computer, Xml.resolvePullParser(it))
}
service.addPackage(pkg1)
@@ -686,6 +691,7 @@
val pkg2 = mockPkgState(PKG_TWO, UUID_TWO, SIGNATURE_TWO,
listOf(DOMAIN_1, DOMAIN_2, DOMAIN_3))
val serviceBefore = makeService(pkg1, pkg2)
+ val computerBefore = mockComputer(pkg1, pkg2)
serviceBefore.addPackage(pkg1)
serviceBefore.addPackage(pkg2)
@@ -729,16 +735,17 @@
assertExpectedState(serviceBefore)
val backupUser0 = ByteArrayOutputStream().use {
- serviceBefore.writeSettings(Xml.resolveSerializer(it), true, 0)
+ serviceBefore.writeSettings(computerBefore, Xml.resolveSerializer(it), true, 0)
it.toByteArray()
}
val backupUser1 = ByteArrayOutputStream().use {
- serviceBefore.writeSettings(Xml.resolveSerializer(it), true, 10)
+ serviceBefore.writeSettings(computerBefore, Xml.resolveSerializer(it), true, 10)
it.toByteArray()
}
val serviceAfter = makeService(pkg1, pkg2)
+ val computerAfter = mockComputer(pkg1, pkg2)
serviceAfter.addPackage(pkg1)
serviceAfter.addPackage(pkg2)
@@ -763,7 +770,7 @@
}
ByteArrayInputStream(backupUser1).use {
- serviceAfter.restoreSettings(Xml.resolvePullParser(it))
+ serviceAfter.restoreSettings(computerAfter, Xml.resolvePullParser(it))
}
// Assert user 1 was restored
@@ -800,7 +807,7 @@
)
ByteArrayInputStream(backupUser0).use {
- serviceAfter.restoreSettings(Xml.resolvePullParser(it))
+ serviceAfter.restoreSettings(computerAfter, Xml.resolvePullParser(it))
}
assertExpectedState(serviceAfter)
@@ -848,12 +855,20 @@
whenever(callingUid) { Process.ROOT_UID }
whenever(callingUserId) { 0 }
- mockPackageStates {
- pkgStateFunction(it)
- }
+ whenever(snapshot()) { mockComputer(pkgStateFunction) }
})
}
+ private fun mockComputer(vararg pkgStates: PackageStateInternal) =
+ mockComputer { pkgName -> pkgStates.find { pkgName == it.packageName } }
+
+ private fun mockComputer(pkgStateFunction: (String) -> PackageStateInternal? = { null }) =
+ mockThrowOnUnmocked<Computer> {
+ whenever(getPackageStateInternal(anyString())) {
+ pkgStateFunction(getArgument(0))
+ }
+ }
+
private fun mockPkgState(
pkgName: String,
domainSetId: UUID,
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
index 3a602a8..fc20c26 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
@@ -29,7 +29,6 @@
import android.util.SparseArray
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
-import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
import com.android.server.pm.verify.domain.DomainVerificationService
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy
@@ -245,10 +244,14 @@
mockThrowOnUnmocked {
whenever(callingUid) { TEST_UID }
whenever(callingUserId) { TEST_USER_ID }
- mockPackageStates {
- when (it) {
- TEST_PKG -> mockPkgState()
- else -> null
+ whenever(snapshot()) {
+ mockThrowOnUnmocked {
+ whenever(getPackageStateInternal(anyString())) {
+ when (getArgument<String>(0)) {
+ TEST_PKG -> mockPkgState()
+ else -> null
+ }
+ }
}
}
whenever(schedule(anyInt(), any()))
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationTestUtils.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationTestUtils.kt
deleted file mode 100644
index c5f0eb1..0000000
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationTestUtils.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.pm.test.verify.domain
-
-import com.android.internal.util.FunctionalUtils
-import com.android.server.pm.pkg.PackageStateInternal
-import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
-import com.android.server.testutils.whenever
-import org.mockito.ArgumentMatchers.any
-import java.util.function.Consumer
-import java.util.function.Function
-
-internal object DomainVerificationTestUtils {
-
- @Suppress("UNCHECKED_CAST")
- fun DomainVerificationManagerInternal.Connection.mockPackageStates(
- block: (String) -> PackageStateInternal?
- ) {
- whenever(withPackageSettingsSnapshot(any())) {
- (arguments[0] as Consumer<Function<String, PackageStateInternal?>>).accept { block(it) }
- }
- whenever(withPackageSettingsSnapshotReturning(any())) {
- (arguments[0] as FunctionalUtils.ThrowingFunction<
- Function<String, PackageStateInternal?>, *>)
- .apply { block(it) }
- }
- whenever(withPackageSettingsSnapshotThrowing<Exception>(any())) {
- (arguments[0] as FunctionalUtils.ThrowingCheckedConsumer<
- Function<String, PackageStateInternal?>, *>)
- .accept { block(it) }
- }
- whenever(withPackageSettingsSnapshotThrowing2<Exception, Exception>(any())) {
- (arguments[0] as FunctionalUtils.ThrowingChecked2Consumer<
- Function<String, PackageStateInternal?>, *, *>)
- .accept { block(it) }
- }
- whenever(withPackageSettingsSnapshotReturningThrowing<Any, Exception>(any())) {
- (arguments[0] as FunctionalUtils.ThrowingCheckedFunction<
- Function<String, PackageStateInternal?>, *, *>)
- .apply { block(it) }
- }
- }
-}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
index ffc2877..589633c 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
@@ -31,7 +31,6 @@
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.pkg.PackageStateInternal
import com.android.server.pm.pkg.PackageUserStateInternal
-import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageStates
import com.android.server.pm.verify.domain.DomainVerificationService
import com.android.server.testutils.mockThrowOnUnmocked
import com.android.server.testutils.whenever
@@ -85,11 +84,15 @@
// Need to provide an internal UID so some permission checks are ignored
whenever(callingUid) { Process.ROOT_UID }
whenever(callingUserId) { 0 }
- mockPackageStates {
- when (it) {
- PKG_ONE -> pkg1
- PKG_TWO -> pkg2
- else -> null
+ whenever(snapshot()) {
+ mockThrowOnUnmocked {
+ whenever(getPackageStateInternal(anyString())) {
+ when (getArgument<String>(0)) {
+ PKG_ONE -> pkg1
+ PKG_TWO -> pkg2
+ else -> null
+ }
+ }
}
}
})
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceControllerTest.java
index 1c480ee..03eff2a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceControllerTest.java
@@ -20,13 +20,18 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
import android.content.pm.UserInfo;
+import android.net.Uri;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
@@ -35,11 +40,13 @@
import com.android.internal.util.ConcurrentUtils;
import com.android.server.SystemService;
+import com.android.server.app.GameServiceConfiguration.GameServiceComponentConfiguration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
@@ -61,10 +68,14 @@
new ComponentName(PROVIDER_A_PACKAGE_NAME, "com.provider.a.ServiceA");
private static final ComponentName PROVIDER_A_SERVICE_B =
new ComponentName(PROVIDER_A_PACKAGE_NAME, "com.provider.a.ServiceB");
+ private static final ComponentName PROVIDER_A_SERVICE_C =
+ new ComponentName(PROVIDER_A_PACKAGE_NAME, "com.provider.a.ServiceC");
private MockitoSession mMockingSession;
private GameServiceController mGameServiceManager;
@Mock
+ private Context mMockContext;
+ @Mock
private GameServiceProviderSelector mMockGameServiceProviderSelector;
@Mock
private GameServiceProviderInstanceFactory mMockGameServiceProviderInstanceFactory;
@@ -77,7 +88,7 @@
.startMocking();
mGameServiceManager = new GameServiceController(
- ConcurrentUtils.DIRECT_EXECUTOR,
+ mMockContext, ConcurrentUtils.DIRECT_EXECUTOR,
mMockGameServiceProviderSelector,
mMockGameServiceProviderInstanceFactory);
}
@@ -96,25 +107,30 @@
@Test
public void notifyUserStarted_createsAndStartsNewInstance() {
- GameServiceProviderConfiguration configurationA =
- new GameServiceProviderConfiguration(USER_HANDLE_10, PROVIDER_A_SERVICE_A,
- PROVIDER_A_SERVICE_B);
+ GameServiceConfiguration configurationA =
+ new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ PROVIDER_A_SERVICE_A,
+ PROVIDER_A_SERVICE_B));
FakeGameServiceProviderInstance instanceA =
seedConfigurationForUser(USER_10, configurationA);
mGameServiceManager.onBootComplete();
mGameServiceManager.notifyUserStarted(USER_10);
- verify(mMockGameServiceProviderInstanceFactory).create(configurationA);
+ verify(mMockGameServiceProviderInstanceFactory).create(
+ configurationA.getGameServiceComponentConfiguration());
verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory);
assertThat(instanceA.getIsRunning()).isTrue();
}
@Test
public void notifyUserStarted_sameUser_doesNotCreateNewInstance() {
- GameServiceProviderConfiguration configurationA =
- new GameServiceProviderConfiguration(USER_HANDLE_10, PROVIDER_A_SERVICE_A,
- PROVIDER_A_SERVICE_B);
+ GameServiceConfiguration configurationA =
+ new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ PROVIDER_A_SERVICE_A,
+ PROVIDER_A_SERVICE_B));
FakeGameServiceProviderInstance instanceA =
seedConfigurationForUser(USER_10, configurationA);
@@ -122,16 +138,19 @@
mGameServiceManager.notifyUserStarted(USER_10);
mGameServiceManager.notifyUserStarted(USER_10);
- verify(mMockGameServiceProviderInstanceFactory).create(configurationA);
+ verify(mMockGameServiceProviderInstanceFactory).create(
+ configurationA.getGameServiceComponentConfiguration());
verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory);
assertThat(instanceA.getIsRunning()).isTrue();
}
@Test
public void notifyUserUnlocking_noForegroundUser_ignores() {
- GameServiceProviderConfiguration configurationA =
- new GameServiceProviderConfiguration(USER_HANDLE_10, PROVIDER_A_SERVICE_A,
- PROVIDER_A_SERVICE_B);
+ GameServiceConfiguration configurationA =
+ new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ PROVIDER_A_SERVICE_A,
+ PROVIDER_A_SERVICE_B));
FakeGameServiceProviderInstance instanceA =
seedConfigurationForUser(USER_10, configurationA);
@@ -144,9 +163,11 @@
@Test
public void notifyUserUnlocking_sameAsForegroundUser_evaluatesProvider() {
- GameServiceProviderConfiguration configurationA =
- new GameServiceProviderConfiguration(USER_HANDLE_10, PROVIDER_A_SERVICE_A,
- PROVIDER_A_SERVICE_B);
+ GameServiceConfiguration configurationA =
+ new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ PROVIDER_A_SERVICE_A,
+ PROVIDER_A_SERVICE_B));
seedNoConfigurationForUser(USER_10);
mGameServiceManager.onBootComplete();
@@ -155,16 +176,19 @@
seedConfigurationForUser(USER_10, configurationA);
mGameServiceManager.notifyUserUnlocking(USER_10);
- verify(mMockGameServiceProviderInstanceFactory).create(configurationA);
+ verify(mMockGameServiceProviderInstanceFactory).create(
+ configurationA.getGameServiceComponentConfiguration());
verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory);
assertThat(instanceA.getIsRunning()).isTrue();
}
@Test
public void notifyUserUnlocking_differentFromForegroundUser_ignores() {
- GameServiceProviderConfiguration configurationA =
- new GameServiceProviderConfiguration(USER_HANDLE_10, PROVIDER_A_SERVICE_A,
- PROVIDER_A_SERVICE_B);
+ GameServiceConfiguration configurationA =
+ new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ PROVIDER_A_SERVICE_A,
+ PROVIDER_A_SERVICE_B));
seedNoConfigurationForUser(USER_10);
mGameServiceManager.onBootComplete();
@@ -180,14 +204,18 @@
@Test
public void
notifyNewForegroundUser_differentUser_stopsPreviousInstanceAndThenStartsNewInstance() {
- GameServiceProviderConfiguration configurationA =
- new GameServiceProviderConfiguration(USER_HANDLE_10, PROVIDER_A_SERVICE_A,
- PROVIDER_A_SERVICE_B);
+ GameServiceConfiguration configurationA =
+ new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ PROVIDER_A_SERVICE_A,
+ PROVIDER_A_SERVICE_B));
FakeGameServiceProviderInstance instanceA =
seedConfigurationForUser(USER_10, configurationA);
- GameServiceProviderConfiguration configurationB =
- new GameServiceProviderConfiguration(USER_HANDLE_11, PROVIDER_A_SERVICE_A,
- PROVIDER_A_SERVICE_B);
+ GameServiceConfiguration configurationB =
+ new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_11,
+ PROVIDER_A_SERVICE_A,
+ PROVIDER_A_SERVICE_B));
FakeGameServiceProviderInstance instanceB = seedConfigurationForUser(USER_11,
configurationB);
InOrder instancesInOrder = Mockito.inOrder(instanceA, instanceB);
@@ -196,8 +224,50 @@
mGameServiceManager.notifyUserStarted(USER_10);
mGameServiceManager.notifyNewForegroundUser(USER_11);
- verify(mMockGameServiceProviderInstanceFactory).create(configurationA);
- verify(mMockGameServiceProviderInstanceFactory).create(configurationB);
+ verify(mMockGameServiceProviderInstanceFactory).create(
+ configurationA.getGameServiceComponentConfiguration());
+ verify(mMockGameServiceProviderInstanceFactory).create(
+ configurationB.getGameServiceComponentConfiguration());
+ instancesInOrder.verify(instanceA).start();
+ instancesInOrder.verify(instanceA).stop();
+ instancesInOrder.verify(instanceB).start();
+ verifyNoMoreInteractions(mMockGameServiceProviderInstanceFactory);
+ assertThat(instanceA.getIsRunning()).isFalse();
+ assertThat(instanceB.getIsRunning()).isTrue();
+ }
+
+ @Test
+ public void packageChanges_reevaluatesGameServiceProvider() {
+ GameServiceConfiguration configurationA =
+ new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ PROVIDER_A_SERVICE_A,
+ PROVIDER_A_SERVICE_B));
+ FakeGameServiceProviderInstance instanceA =
+ seedConfigurationForUser(USER_10, configurationA);
+
+ mGameServiceManager.onBootComplete();
+ mGameServiceManager.notifyUserStarted(USER_10);
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverArgumentCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext).registerReceiver(broadcastReceiverArgumentCaptor.capture(), any());
+
+ GameServiceConfiguration configurationB =
+ new GameServiceConfiguration(PROVIDER_A_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ PROVIDER_A_SERVICE_A,
+ PROVIDER_A_SERVICE_C));
+ FakeGameServiceProviderInstance instanceB =
+ seedConfigurationForUser(USER_10, configurationA);
+ Intent intent = new Intent();
+ intent.setData(Uri.parse("package:" + PROVIDER_A_PACKAGE_NAME));
+ broadcastReceiverArgumentCaptor.getValue().onReceive(mMockContext, intent);
+
+ InOrder instancesInOrder = Mockito.inOrder(instanceA, instanceB);
+ verify(mMockGameServiceProviderInstanceFactory).create(
+ configurationA.getGameServiceComponentConfiguration());
+ verify(mMockGameServiceProviderInstanceFactory).create(
+ configurationB.getGameServiceComponentConfiguration());
instancesInOrder.verify(instanceA).start();
instancesInOrder.verify(instanceA).stop();
instancesInOrder.verify(instanceB).start();
@@ -207,15 +277,16 @@
}
private void seedNoConfigurationForUser(SystemService.TargetUser user) {
- when(mMockGameServiceProviderSelector.get(user, "")).thenReturn(null);
+ when(mMockGameServiceProviderSelector.get(user, null)).thenReturn(null);
}
private FakeGameServiceProviderInstance seedConfigurationForUser(SystemService.TargetUser user,
- GameServiceProviderConfiguration configuration) {
- when(mMockGameServiceProviderSelector.get(user, "")).thenReturn(configuration);
+ GameServiceConfiguration configuration) {
+ when(mMockGameServiceProviderSelector.get(user, null)).thenReturn(configuration);
FakeGameServiceProviderInstance instanceForConfiguration =
spy(new FakeGameServiceProviderInstance());
- when(mMockGameServiceProviderInstanceFactory.create(configuration))
+ when(mMockGameServiceProviderInstanceFactory.create(
+ configuration.getGameServiceComponentConfiguration()))
.thenReturn(instanceForConfiguration);
return instanceForConfiguration;
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderSelectorImplTest.java b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderSelectorImplTest.java
index 23a6a49..cf9ba1e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderSelectorImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderSelectorImplTest.java
@@ -18,6 +18,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.google.common.truth.Truth.assertThat;
@@ -26,7 +27,6 @@
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
@@ -49,6 +49,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.server.SystemService;
+import com.android.server.app.GameServiceConfiguration.GameServiceComponentConfiguration;
import com.google.common.collect.ImmutableList;
@@ -137,10 +138,10 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_valid.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(null, null);
- assertThat(gameServiceProviderConfiguration).isNull();
+ assertThat(gameServiceConfiguration).isNull();
}
@Test
@@ -154,15 +155,16 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_valid.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(managedTargetUser(USER_HANDLE_10), null);
- assertThat(gameServiceProviderConfiguration).isNull();
+ assertThat(gameServiceConfiguration).isNull();
}
@Test
public void get_noSystemGameService_returnsNull()
throws Exception {
+ seedSystemGameServicePackageName("");
seedGameServiceResolveInfos(GAME_SERVICE_PACKAGE_NAME, USER_HANDLE_10,
resolveInfo(GAME_SERVICE_SERVICE_INFO));
seedServiceServiceInfo(GAME_SESSION_SERVICE_COMPONENT);
@@ -170,14 +172,14 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_valid.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(eligibleTargetUser(USER_HANDLE_10), null);
- assertThat(gameServiceProviderConfiguration).isNull();
+ assertThat(gameServiceConfiguration).isNull();
}
@Test
- public void get_noGameServiceProvidersAvailable_returnsNull()
+ public void get_noGameServiceProvidersAvailable_returnsGameServicePackageName()
throws Exception {
seedSystemGameServicePackageName(GAME_SERVICE_PACKAGE_NAME);
seedGameServiceResolveInfos(GAME_SERVICE_PACKAGE_NAME, USER_HANDLE_10);
@@ -186,28 +188,30 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_valid.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(eligibleTargetUser(USER_HANDLE_10), null);
- assertThat(gameServiceProviderConfiguration).isNull();
+ assertThat(gameServiceConfiguration).isEqualTo(
+ new GameServiceConfiguration(GAME_SERVICE_PACKAGE_NAME, null));
}
@Test
- public void get_gameServiceProviderHasNoMetaData_returnsNull()
+ public void get_gameServiceProviderHasNoMetaData_returnsGameServicePackageName()
throws Exception {
seedSystemGameServicePackageName(GAME_SERVICE_PACKAGE_NAME);
seedGameServiceResolveInfos(GAME_SERVICE_PACKAGE_NAME, USER_HANDLE_10,
resolveInfo(GAME_SERVICE_SERVICE_INFO_WITHOUT_META_DATA));
seedServiceServiceInfo(GAME_SESSION_SERVICE_COMPONENT);
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(eligibleTargetUser(USER_HANDLE_10), null);
- assertThat(gameServiceProviderConfiguration).isNull();
+ assertThat(gameServiceConfiguration).isEqualTo(
+ new GameServiceConfiguration(GAME_SERVICE_PACKAGE_NAME, null));
}
@Test
- public void get_gameSessionServiceDoesNotExist_returnsNull()
+ public void get_gameSessionServiceDoesNotExist_returnsGameServicePackageName()
throws Exception {
seedSystemGameServicePackageName(GAME_SERVICE_PACKAGE_NAME);
seedGameServiceResolveInfos(GAME_SERVICE_PACKAGE_NAME, USER_HANDLE_10,
@@ -217,14 +221,15 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_valid.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(eligibleTargetUser(USER_HANDLE_10), null);
- assertThat(gameServiceProviderConfiguration).isNull();
+ assertThat(gameServiceConfiguration).isEqualTo(
+ new GameServiceConfiguration(GAME_SERVICE_PACKAGE_NAME, null));
}
@Test
- public void get_metaDataWrongFirstTag_returnsNull() throws Exception {
+ public void get_metaDataWrongFirstTag_returnsGameServicePackageName() throws Exception {
seedSystemGameServicePackageName(GAME_SERVICE_PACKAGE_NAME);
seedGameServiceResolveInfos(GAME_SERVICE_PACKAGE_NAME, USER_HANDLE_10,
resolveInfo(GAME_SERVICE_SERVICE_INFO));
@@ -233,10 +238,11 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_wrong_first_tag.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(eligibleTargetUser(USER_HANDLE_10), null);
- assertThat(gameServiceProviderConfiguration).isNull();
+ assertThat(gameServiceConfiguration).isEqualTo(
+ new GameServiceConfiguration(GAME_SERVICE_PACKAGE_NAME, null));
}
@Test
@@ -250,15 +256,17 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_valid.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(eligibleTargetUser(USER_HANDLE_10), null);
- GameServiceProviderConfiguration expectedGameServiceProviderConfiguration =
- new GameServiceProviderConfiguration(USER_HANDLE_10,
- GAME_SERVICE_COMPONENT,
- GAME_SESSION_SERVICE_COMPONENT);
- assertThat(gameServiceProviderConfiguration).isEqualTo(
- expectedGameServiceProviderConfiguration);
+ GameServiceConfiguration expectedGameServiceConfiguration =
+ new GameServiceConfiguration(
+ GAME_SERVICE_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ GAME_SERVICE_COMPONENT,
+ GAME_SESSION_SERVICE_COMPONENT));
+ assertThat(gameServiceConfiguration).isEqualTo(
+ expectedGameServiceConfiguration);
}
@Test
@@ -276,15 +284,17 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_valid.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(eligibleTargetUser(USER_HANDLE_10), null);
- GameServiceProviderConfiguration expectedGameServiceProviderConfiguration =
- new GameServiceProviderConfiguration(USER_HANDLE_10,
- GAME_SERVICE_B_COMPONENT,
- GAME_SESSION_SERVICE_COMPONENT);
- assertThat(gameServiceProviderConfiguration).isEqualTo(
- expectedGameServiceProviderConfiguration);
+ GameServiceConfiguration expectedGameServiceConfiguration =
+ new GameServiceConfiguration(
+ GAME_SERVICE_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ GAME_SERVICE_B_COMPONENT,
+ GAME_SESSION_SERVICE_COMPONENT));
+ assertThat(gameServiceConfiguration).isEqualTo(
+ expectedGameServiceConfiguration);
}
@Test
@@ -299,15 +309,17 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_valid.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(eligibleTargetUser(USER_HANDLE_10), null);
- GameServiceProviderConfiguration expectedGameServiceProviderConfiguration =
- new GameServiceProviderConfiguration(USER_HANDLE_10,
- GAME_SERVICE_COMPONENT,
- GAME_SESSION_SERVICE_COMPONENT);
- assertThat(gameServiceProviderConfiguration).isEqualTo(
- expectedGameServiceProviderConfiguration);
+ GameServiceConfiguration expectedGameServiceConfiguration =
+ new GameServiceConfiguration(
+ GAME_SERVICE_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(USER_HANDLE_10,
+ GAME_SERVICE_COMPONENT,
+ GAME_SESSION_SERVICE_COMPONENT));
+ assertThat(gameServiceConfiguration).isEqualTo(
+ expectedGameServiceConfiguration);
}
@Test
@@ -322,16 +334,19 @@
GAME_SERVICE_META_DATA_RES_ID,
"res/xml/game_service_metadata_valid.xml");
- GameServiceProviderConfiguration gameServiceProviderConfiguration =
+ GameServiceConfiguration gameServiceConfiguration =
mGameServiceProviderSelector.get(eligibleTargetUser(USER_HANDLE_10),
GAME_SERVICE_PACKAGE_NAME);
- GameServiceProviderConfiguration expectedGameServiceProviderConfiguration =
- new GameServiceProviderConfiguration(USER_HANDLE_10,
- GAME_SERVICE_COMPONENT,
- GAME_SESSION_SERVICE_COMPONENT);
- assertThat(gameServiceProviderConfiguration).isEqualTo(
- expectedGameServiceProviderConfiguration);
+ GameServiceConfiguration expectedGameServiceConfiguration =
+ new GameServiceConfiguration(
+ GAME_SERVICE_PACKAGE_NAME,
+ new GameServiceComponentConfiguration(
+ USER_HANDLE_10,
+ GAME_SERVICE_COMPONENT,
+ GAME_SESSION_SERVICE_COMPONENT));
+ assertThat(gameServiceConfiguration).isEqualTo(
+ expectedGameServiceConfiguration);
}
private void seedSystemGameServicePackageName(String gameServicePackageName) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index ca5bf20..6510cd1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -167,7 +167,7 @@
}
whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap)
whenever(mocks.settings.getPackageLPr(anyString())) { mSettingsMap[getArgument<Any>(0)] }
- whenever(mocks.settings.readLPw(nullable())) {
+ whenever(mocks.settings.readLPw(any(), nullable())) {
mSettingsMap.putAll(mPreExistingSettings)
!mPreExistingSettings.isEmpty()
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
index f35986b..b063d22 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
@@ -120,17 +120,16 @@
whenever(mStorageManager.findPathForUuid(nullable())).thenReturn(mFile)
doAnswer { it.arguments[0] }.`when`(mPms).resolveInternalPackageName(any(), any())
doAnswer {
- it.getArgument<FunctionalUtils.ThrowingConsumer<Computer>>(0).acceptOrThrow(
- mockThrowOnUnmocked {
- whenever(sharedLibraries) { mSharedLibrariesImpl.sharedLibraries }
- whenever(resolveInternalPackageName(anyString(), anyLong())) {
- mPms.resolveInternalPackageName(getArgument(0), getArgument(1))
- }
- whenever(getPackageStateInternal(anyString())) {
- mPms.getPackageStateInternal(getArgument(0))
- }
- })
- }.`when`(mPms).executeWithConsistentComputer(any())
+ mockThrowOnUnmocked<Computer> {
+ whenever(sharedLibraries) { mSharedLibrariesImpl.sharedLibraries }
+ whenever(resolveInternalPackageName(anyString(), anyLong())) {
+ mPms.resolveInternalPackageName(getArgument(0), getArgument(1))
+ }
+ whenever(getPackageStateInternal(anyString())) {
+ mPms.getPackageStateInternal(getArgument(0))
+ }
+ }
+ }.`when`(mPms).snapshotComputer()
whenever(mDeletePackageHelper.deletePackageX(any(), any(), any(), any(), any()))
.thenReturn(PackageManager.DELETE_SUCCEEDED)
whenever(mRule.mocks().injector.compatibility).thenReturn(mPlatformCompat)
@@ -206,7 +205,8 @@
@Test
fun pruneUnusedStaticSharedLibraries() {
- mSharedLibrariesImpl.pruneUnusedStaticSharedLibraries(Long.MAX_VALUE, 0)
+ mSharedLibrariesImpl.pruneUnusedStaticSharedLibraries(mPms.snapshotComputer(),
+ Long.MAX_VALUE, 0)
verify(mDeletePackageHelper)
.deletePackageX(eq(STATIC_LIB_PACKAGE_NAME), any(), any(), any(), any())
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
index ac406b5..5230ea7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
@@ -123,8 +123,8 @@
@Test
fun setPackagesSuspended() {
val targetPackages = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2)
- val failedNames = suspendPackageHelper.setPackagesSuspended(targetPackages,
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
+ val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ targetPackages, true /* suspended */, null /* appExtras */, null /* launcherExtras */,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
testHandler.flush()
@@ -144,14 +144,15 @@
@Test
fun setPackagesSuspended_emptyPackageName() {
- var failedNames = suspendPackageHelper.setPackagesSuspended(null /* packageNames */,
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
- null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
+ var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ null /* packageNames */, true /* suspended */, null /* appExtras */,
+ null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID,
+ deviceOwnerUid)
assertThat(failedNames).isNull()
- failedNames = suspendPackageHelper.setPackagesSuspended(arrayOfNulls(0),
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
+ failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ arrayOfNulls(0), true /* suspended */, null /* appExtras */, null /* launcherExtras */,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
assertThat(failedNames).isEmpty()
@@ -159,9 +160,10 @@
@Test
fun setPackagesSuspended_callerIsNotAllowed() {
- val failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_2),
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
- null /* dialogInfo */, TEST_PACKAGE_1, TEST_USER_ID, Binder.getCallingUid())
+ val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */,
+ null /* launcherExtras */, null /* dialogInfo */, TEST_PACKAGE_1, TEST_USER_ID,
+ Binder.getCallingUid())
assertThat(failedNames).asList().hasSize(1)
assertThat(failedNames).asList().contains(TEST_PACKAGE_2)
@@ -169,9 +171,10 @@
@Test
fun setPackagesSuspended_callerSuspendItself() {
- val failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(DEVICE_OWNER_PACKAGE),
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
- null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
+ val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ arrayOf(DEVICE_OWNER_PACKAGE), true /* suspended */, null /* appExtras */,
+ null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID,
+ deviceOwnerUid)
assertThat(failedNames).asList().hasSize(1)
assertThat(failedNames).asList().contains(DEVICE_OWNER_PACKAGE)
@@ -179,9 +182,10 @@
@Test
fun setPackagesSuspended_nonexistentPackage() {
- val failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(NONEXISTENT_PACKAGE),
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
- null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
+ val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ arrayOf(NONEXISTENT_PACKAGE), true /* suspended */, null /* appExtras */,
+ null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID,
+ deviceOwnerUid)
assertThat(failedNames).asList().hasSize(1)
assertThat(failedNames).asList().contains(NONEXISTENT_PACKAGE)
@@ -191,8 +195,8 @@
fun setPackagesSuspended_knownPackages() {
val knownPackages = arrayOf(DEVICE_ADMIN_PACKAGE, DEFAULT_HOME_PACKAGE, DIALER_PACKAGE,
INSTALLER_PACKAGE, UNINSTALLER_PACKAGE, VERIFIER_PACKAGE, PERMISSION_CONTROLLER_PACKAGE)
- val failedNames = suspendPackageHelper.setPackagesSuspended(knownPackages,
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
+ val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ knownPackages, true /* suspended */, null /* appExtras */, null /* launcherExtras */,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)!!
assertThat(failedNames.size).isEqualTo(knownPackages.size)
@@ -204,13 +208,13 @@
@Test
fun setPackagesUnsuspended() {
val targetPackages = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2)
- var failedNames = suspendPackageHelper.setPackagesSuspended(targetPackages,
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
+ var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ targetPackages, true /* suspended */, null /* appExtras */, null /* launcherExtras */,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
testHandler.flush()
assertThat(failedNames).isEmpty()
- failedNames = suspendPackageHelper.setPackagesSuspended(targetPackages,
- false /* suspended */, null /* appExtras */, null /* launcherExtras */,
+ failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ targetPackages, false /* suspended */, null /* appExtras */, null /* launcherExtras */,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
testHandler.flush()
@@ -235,7 +239,7 @@
val suspendables = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2)
val unsuspendables = arrayOf(DEVICE_ADMIN_PACKAGE, DEFAULT_HOME_PACKAGE, DIALER_PACKAGE,
INSTALLER_PACKAGE, UNINSTALLER_PACKAGE, VERIFIER_PACKAGE, PERMISSION_CONTROLLER_PACKAGE)
- val results = suspendPackageHelper.getUnsuspendablePackagesForUser(
+ val results = suspendPackageHelper.getUnsuspendablePackagesForUser(pms.snapshotComputer(),
suspendables + unsuspendables, TEST_USER_ID, deviceOwnerUid)
assertThat(results.size).isEqualTo(unsuspendables.size)
@@ -247,7 +251,7 @@
@Test
fun getUnsuspendablePackagesForUser_callerIsNotAllowed() {
val suspendables = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2)
- val results = suspendPackageHelper.getUnsuspendablePackagesForUser(
+ val results = suspendPackageHelper.getUnsuspendablePackagesForUser(pms.snapshotComputer(),
suspendables, TEST_USER_ID, Binder.getCallingUid())
assertThat(results.size).isEqualTo(suspendables.size)
@@ -260,8 +264,8 @@
fun getSuspendedPackageAppExtras() {
val appExtras = PersistableBundle()
appExtras.putString(TEST_PACKAGE_1, TEST_PACKAGE_1)
- var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_1),
- true /* suspended */, appExtras, null /* launcherExtras */,
+ var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ arrayOf(TEST_PACKAGE_1), true /* suspended */, appExtras, null /* launcherExtras */,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -277,8 +281,8 @@
val appExtras = PersistableBundle()
appExtras.putString(TEST_PACKAGE_1, TEST_PACKAGE_2)
val targetPackages = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2)
- var failedNames = suspendPackageHelper.setPackagesSuspended(targetPackages,
- true /* suspended */, appExtras, null /* launcherExtras */,
+ var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ targetPackages, true /* suspended */, appExtras, null /* launcherExtras */,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -291,8 +295,9 @@
assertThat(suspendPackageHelper.getSuspendedPackageAppExtras(
TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNotNull()
- suspendPackageHelper.removeSuspensionsBySuspendingPackage(targetPackages,
- { suspendingPackage -> suspendingPackage == DEVICE_OWNER_PACKAGE }, TEST_USER_ID)
+ suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(),
+ targetPackages, { suspendingPackage -> suspendingPackage == DEVICE_OWNER_PACKAGE },
+ TEST_USER_ID)
testHandler.flush()
verify(pms, times(2)).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
@@ -320,8 +325,8 @@
fun getSuspendedPackageLauncherExtras() {
val launcherExtras = PersistableBundle()
launcherExtras.putString(TEST_PACKAGE_2, TEST_PACKAGE_2)
- var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_2),
- true /* suspended */, null /* appExtras */, launcherExtras,
+ var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */, launcherExtras,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -334,9 +339,10 @@
@Test
fun isPackageSuspended() {
- var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_1),
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
- null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
+ var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ arrayOf(TEST_PACKAGE_1), true /* suspended */, null /* appExtras */,
+ null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID,
+ deviceOwnerUid)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -348,8 +354,8 @@
fun getSuspendingPackage() {
val launcherExtras = PersistableBundle()
launcherExtras.putString(TEST_PACKAGE_2, TEST_PACKAGE_2)
- var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_2),
- true /* suspended */, null /* appExtras */, launcherExtras,
+ var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */, launcherExtras,
null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
testHandler.flush()
assertThat(failedNames).isEmpty()
@@ -362,9 +368,10 @@
fun getSuspendedDialogInfo() {
val dialogInfo = SuspendDialogInfo.Builder()
.setTitle(TEST_PACKAGE_1).build()
- var failedNames = suspendPackageHelper.setPackagesSuspended(arrayOf(TEST_PACKAGE_1),
- true /* suspended */, null /* appExtras */, null /* launcherExtras */,
- dialogInfo, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid)
+ var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+ arrayOf(TEST_PACKAGE_1), true /* suspended */, null /* appExtras */,
+ null /* launcherExtras */, dialogInfo, DEVICE_OWNER_PACKAGE, TEST_USER_ID,
+ deviceOwnerUid)
testHandler.flush()
assertThat(failedNames).isEmpty()
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 6789af4..2b34bc2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -35,6 +35,7 @@
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
@@ -109,6 +110,8 @@
LegacyPermissionDataProvider mPermissionDataProvider;
@Mock
DomainVerificationManagerInternal mDomainVerificationManager;
+ @Mock
+ Computer computer;
final ArrayMap<String, Long> mOrigFirstInstallTimes = new ArrayMap<>();
@@ -132,7 +135,7 @@
/* write out files and read */
writeOldFiles();
Settings settings = makeSettings();
- assertThat(settings.readLPw(createFakeUsers()), is(true));
+ assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
}
@@ -143,11 +146,11 @@
// write out files and read
writeOldFiles();
Settings settings = makeSettings();
- assertThat(settings.readLPw(createFakeUsers()), is(true));
+ assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
// write out, read back in and verify the same
- settings.writeLPr();
- assertThat(settings.readLPw(createFakeUsers()), is(true));
+ settings.writeLPr(computer);
+ assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
}
@@ -156,7 +159,7 @@
// Write delegateshellthe package files and make sure they're parsed properly the first time
writeOldFiles();
Settings settings = makeSettings();
- assertThat(settings.readLPw(createFakeUsers()), is(true));
+ assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
assertThat(settings.getPackageLPr(PACKAGE_NAME_3), is(notNullValue()));
assertThat(settings.getPackageLPr(PACKAGE_NAME_1), is(notNullValue()));
@@ -175,12 +178,12 @@
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
Settings settings = makeSettings();
- assertThat(settings.readLPw(createFakeUsers()), is(true));
- settings.writeLPr();
+ assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
+ settings.writeLPr(computer);
// Create Settings again to make it read from the new files
settings = makeSettings();
- assertThat(settings.readLPw(createFakeUsers()), is(true));
+ assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_2);
assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER));
@@ -469,12 +472,12 @@
ps2.setUsesStaticLibrariesVersions(new long[] { 34 });
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
- settingsUnderTest.writeLPr();
+ settingsUnderTest.writeLPr(computer);
settingsUnderTest.mPackages.clear();
settingsUnderTest.mDisabledSysPackages.clear();
- assertThat(settingsUnderTest.readLPw(createFakeUsers()), is(true));
+ assertThat(settingsUnderTest.readLPw(computer, createFakeUsers()), is(true));
PackageSetting readPs1 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_1);
PackageSetting readPs2 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_2);
@@ -534,12 +537,12 @@
ps2.setUsesSdkLibrariesVersionsMajor(new long[] { 34 });
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
- settingsUnderTest.writeLPr();
+ settingsUnderTest.writeLPr(computer);
settingsUnderTest.mPackages.clear();
settingsUnderTest.mDisabledSysPackages.clear();
- assertThat(settingsUnderTest.readLPw(createFakeUsers()), is(true));
+ assertThat(settingsUnderTest.readLPw(computer, createFakeUsers()), is(true));
PackageSetting readPs1 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_1);
PackageSetting readPs2 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_2);
@@ -587,7 +590,7 @@
Settings settings = makeSettings();
final WatchableTester watcher = new WatchableTester(settings, "testEnableDisable");
watcher.register();
- assertThat(settings.readLPw(createFakeUsers()), is(true));
+ assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
watcher.verifyChangeReported("readLPw");
// Enable/Disable a package