Merge "Throttle the repeated silent installation requests" into sc-dev
This commit is contained in:
@@ -61,4 +61,6 @@ interface IPackageInstaller {
|
|||||||
void setPermissionsResult(int sessionId, boolean accepted);
|
void setPermissionsResult(int sessionId, boolean accepted);
|
||||||
|
|
||||||
void bypassNextStagedInstallerCheck(boolean value);
|
void bypassNextStagedInstallerCheck(boolean value);
|
||||||
|
|
||||||
|
void setAllowUnlimitedSilentUpdates(String installerPackageName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.AppGlobals;
|
import android.app.AppGlobals;
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
@@ -194,6 +195,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
|||||||
@GuardedBy("mSessions")
|
@GuardedBy("mSessions")
|
||||||
private final SparseBooleanArray mLegacySessions = new SparseBooleanArray();
|
private final SparseBooleanArray mLegacySessions = new SparseBooleanArray();
|
||||||
|
|
||||||
|
/** Policy for allowing a silent update. */
|
||||||
|
private final SilentUpdatePolicy mSilentUpdatePolicy = new SilentUpdatePolicy();
|
||||||
|
|
||||||
private static final FilenameFilter sStageFilter = new FilenameFilter() {
|
private static final FilenameFilter sStageFilter = new FilenameFilter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(File dir, String name) {
|
public boolean accept(File dir, String name) {
|
||||||
@@ -409,7 +413,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
|||||||
try {
|
try {
|
||||||
session = PackageInstallerSession.readFromXml(in, mInternalCallback,
|
session = PackageInstallerSession.readFromXml(in, mInternalCallback,
|
||||||
mContext, mPm, mInstallThread.getLooper(), mStagingManager,
|
mContext, mPm, mInstallThread.getLooper(), mStagingManager,
|
||||||
mSessionsDir, this);
|
mSessionsDir, this, mSilentUpdatePolicy);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Slog.e(TAG, "Could not read session", e);
|
Slog.e(TAG, "Could not read session", e);
|
||||||
continue;
|
continue;
|
||||||
@@ -755,10 +759,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
|||||||
originatingPackageName, requestedInstallerPackageName,
|
originatingPackageName, requestedInstallerPackageName,
|
||||||
installerAttributionTag);
|
installerAttributionTag);
|
||||||
session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
|
session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
|
||||||
mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid,
|
mSilentUpdatePolicy, mInstallThread.getLooper(), mStagingManager, sessionId,
|
||||||
installSource, params, createdMillis, 0L, stageDir, stageCid, null, null, false,
|
userId, callingUid, installSource, params, createdMillis, 0L, stageDir, stageCid,
|
||||||
false, false, false, null, SessionInfo.INVALID_ID, false, false, false,
|
null, null, false, false, false, false, null, SessionInfo.INVALID_ID,
|
||||||
SessionInfo.STAGED_SESSION_NO_ERROR, "");
|
false, false, false, SessionInfo.STAGED_SESSION_NO_ERROR, "");
|
||||||
|
|
||||||
synchronized (mSessions) {
|
synchronized (mSessions) {
|
||||||
mSessions.put(sessionId, session);
|
mSessions.put(sessionId, session);
|
||||||
@@ -1087,6 +1091,17 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
|||||||
mBypassNextStagedInstallerCheck = value;
|
mBypassNextStagedInstallerCheck = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an installer to allow for the unlimited silent updates.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setAllowUnlimitedSilentUpdates(@Nullable String installerPackageName) {
|
||||||
|
if (!isCalledBySystemOrShell(Binder.getCallingUid())) {
|
||||||
|
throw new SecurityException("Caller not allowed to unlimite silent updates");
|
||||||
|
}
|
||||||
|
mSilentUpdatePolicy.setAllowUnlimitedSilentUpdates(installerPackageName);
|
||||||
|
}
|
||||||
|
|
||||||
private static int getSessionCount(SparseArray<PackageInstallerSession> sessions,
|
private static int getSessionCount(SparseArray<PackageInstallerSession> sessions,
|
||||||
int installerUid) {
|
int installerUid) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -1369,8 +1384,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
|||||||
pw.println("Legacy install sessions:");
|
pw.println("Legacy install sessions:");
|
||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
pw.println(mLegacySessions.toString());
|
pw.println(mLegacySessions.toString());
|
||||||
|
pw.println();
|
||||||
pw.decreaseIndent();
|
pw.decreaseIndent();
|
||||||
}
|
}
|
||||||
|
mSilentUpdatePolicy.dump(pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
class InternalCallback {
|
class InternalCallback {
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
private final PackageManagerService mPm;
|
private final PackageManagerService mPm;
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final PackageSessionProvider mSessionProvider;
|
private final PackageSessionProvider mSessionProvider;
|
||||||
|
private final SilentUpdatePolicy mSilentUpdatePolicy;
|
||||||
/**
|
/**
|
||||||
* Note all calls must be done outside {@link #mLock} to prevent lock inversion.
|
* Note all calls must be done outside {@link #mLock} to prevent lock inversion.
|
||||||
*/
|
*/
|
||||||
@@ -995,8 +996,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
|
public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
|
||||||
Context context, PackageManagerService pm,
|
Context context, PackageManagerService pm, PackageSessionProvider sessionProvider,
|
||||||
PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager,
|
SilentUpdatePolicy silentUpdatePolicy, Looper looper, StagingManager stagingManager,
|
||||||
int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
|
int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
|
||||||
SessionParams params, long createdMillis, long committedMillis,
|
SessionParams params, long createdMillis, long committedMillis,
|
||||||
File stageDir, String stageCid, InstallationFile[] files,
|
File stageDir, String stageCid, InstallationFile[] files,
|
||||||
@@ -1009,6 +1010,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
mPm = pm;
|
mPm = pm;
|
||||||
mSessionProvider = sessionProvider;
|
mSessionProvider = sessionProvider;
|
||||||
|
mSilentUpdatePolicy = silentUpdatePolicy;
|
||||||
mHandler = new Handler(looper, mHandlerCallback);
|
mHandler = new Handler(looper, mHandlerCallback);
|
||||||
mStagingManager = stagingManager;
|
mStagingManager = stagingManager;
|
||||||
|
|
||||||
@@ -2384,6 +2386,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
} // else, we'll wait until we parse to determine if we need to
|
} // else, we'll wait until we parse to determine if we need to
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean silentUpdatePolicyEnforceable = false;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mRelinquished) {
|
if (mRelinquished) {
|
||||||
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
|
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
|
||||||
@@ -2408,12 +2411,28 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
extractNativeLibraries(
|
extractNativeLibraries(
|
||||||
mPackageLite, stageDir, params.abiOverride, mayInheritNativeLibs());
|
mPackageLite, stageDir, params.abiOverride, mayInheritNativeLibs());
|
||||||
|
|
||||||
if (userActionRequirement == USER_ACTION_PENDING_APK_PARSING
|
if (userActionRequirement == USER_ACTION_PENDING_APK_PARSING) {
|
||||||
&& (result.getTargetSdk() < Build.VERSION_CODES.Q)) {
|
if (result.getTargetSdk() < Build.VERSION_CODES.Q) {
|
||||||
sendPendingUserActionIntent();
|
sendPendingUserActionIntent();
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
if (params.requireUserAction == SessionParams.USER_ACTION_NOT_REQUIRED) {
|
||||||
|
silentUpdatePolicyEnforceable = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (silentUpdatePolicyEnforceable) {
|
||||||
|
if (!mSilentUpdatePolicy.isSilentUpdateAllowed(
|
||||||
|
getInstallerPackageName(), getPackageName())) {
|
||||||
|
// Fall back to the non-silent update if a repeated installation is invoked within
|
||||||
|
// the throttle time.
|
||||||
|
sendPendingUserActionIntent();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
mSilentUpdatePolicy.track(getInstallerPackageName(), getPackageName());
|
||||||
|
}
|
||||||
|
synchronized (mLock) {
|
||||||
return makeVerificationParamsLocked();
|
return makeVerificationParamsLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4569,7 +4588,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
@NonNull PackageInstallerService.InternalCallback callback, @NonNull Context context,
|
@NonNull PackageInstallerService.InternalCallback callback, @NonNull Context context,
|
||||||
@NonNull PackageManagerService pm, Looper installerThread,
|
@NonNull PackageManagerService pm, Looper installerThread,
|
||||||
@NonNull StagingManager stagingManager, @NonNull File sessionsDir,
|
@NonNull StagingManager stagingManager, @NonNull File sessionsDir,
|
||||||
@NonNull PackageSessionProvider sessionProvider)
|
@NonNull PackageSessionProvider sessionProvider,
|
||||||
|
@NonNull SilentUpdatePolicy silentUpdatePolicy)
|
||||||
throws IOException, XmlPullParserException {
|
throws IOException, XmlPullParserException {
|
||||||
final int sessionId = in.getAttributeInt(null, ATTR_SESSION_ID);
|
final int sessionId = in.getAttributeInt(null, ATTR_SESSION_ID);
|
||||||
final int userId = in.getAttributeInt(null, ATTR_USER_ID);
|
final int userId = in.getAttributeInt(null, ATTR_USER_ID);
|
||||||
@@ -4743,10 +4763,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
|
|
||||||
InstallSource installSource = InstallSource.create(installInitiatingPackageName,
|
InstallSource installSource = InstallSource.create(installInitiatingPackageName,
|
||||||
installOriginatingPackageName, installerPackageName, installerAttributionTag);
|
installOriginatingPackageName, installerPackageName, installerAttributionTag);
|
||||||
return new PackageInstallerSession(callback, context, pm, sessionProvider, installerThread,
|
return new PackageInstallerSession(callback, context, pm, sessionProvider,
|
||||||
stagingManager, sessionId, userId, installerUid, installSource, params,
|
silentUpdatePolicy, installerThread, stagingManager, sessionId, userId,
|
||||||
createdMillis, committedMillis, stageDir, stageCid, fileArray, checksumsMap,
|
installerUid, installSource, params, createdMillis, committedMillis, stageDir,
|
||||||
prepared, committed, destroyed, sealed, childSessionIdsArray, parentSessionId,
|
stageCid, fileArray, checksumsMap, prepared, committed, destroyed, sealed,
|
||||||
isReady, isFailed, isApplied, stagedSessionErrorCode, stagedSessionErrorMessage);
|
childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied,
|
||||||
|
stagedSessionErrorCode, stagedSessionErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -304,6 +304,8 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
return runLogVisibility();
|
return runLogVisibility();
|
||||||
case "bypass-staged-installer-check":
|
case "bypass-staged-installer-check":
|
||||||
return runBypassStagedInstallerCheck();
|
return runBypassStagedInstallerCheck();
|
||||||
|
case "allow-unlimited-silent-updates":
|
||||||
|
return runAllowUnlimitedSilentUpdates();
|
||||||
default: {
|
default: {
|
||||||
Boolean domainVerificationResult =
|
Boolean domainVerificationResult =
|
||||||
mDomainVerificationShell.runCommand(this, cmd);
|
mDomainVerificationShell.runCommand(this, cmd);
|
||||||
@@ -2978,6 +2980,33 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int runAllowUnlimitedSilentUpdates() {
|
||||||
|
final PrintWriter pw = getOutPrintWriter();
|
||||||
|
String opt;
|
||||||
|
boolean reset = false;
|
||||||
|
while ((opt = getNextOption()) != null) {
|
||||||
|
switch (opt) {
|
||||||
|
case "--reset":
|
||||||
|
reset = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pw.println("Error: Unknown option: " + opt);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final String installerPackageName = reset ? null : getNextArgRequired();
|
||||||
|
try {
|
||||||
|
mInterface.getPackageInstaller().setAllowUnlimitedSilentUpdates(installerPackageName);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
pw.println("Failure ["
|
||||||
|
+ e.getClass().getName() + " - "
|
||||||
|
+ e.getMessage() + "]");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
private static String checkAbiArgument(String abi) {
|
private static String checkAbiArgument(String abi) {
|
||||||
if (TextUtils.isEmpty(abi)) {
|
if (TextUtils.isEmpty(abi)) {
|
||||||
throw new IllegalArgumentException("Missing ABI argument");
|
throw new IllegalArgumentException("Missing ABI argument");
|
||||||
@@ -3792,6 +3821,12 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
pw.println(" --enable: turn on debug logging (default)");
|
pw.println(" --enable: turn on debug logging (default)");
|
||||||
pw.println(" --disable: turn off debug logging");
|
pw.println(" --disable: turn off debug logging");
|
||||||
pw.println("");
|
pw.println("");
|
||||||
|
pw.println(" allow-unlimited-silent-updates (--reset | <INSTALLER>)");
|
||||||
|
pw.println(" Allows unlimited silent updated installation requests from the installer");
|
||||||
|
pw.println(" without the throttle time.");
|
||||||
|
pw.println(" --reset: clear the allowed installer and tracks of silent updates in");
|
||||||
|
pw.println(" the system.");
|
||||||
|
pw.println("");
|
||||||
mDomainVerificationShell.printHelp(pw);
|
mDomainVerificationShell.printHelp(pw);
|
||||||
pw.println("");
|
pw.println("");
|
||||||
Intent.printIntentArgsHelp(pw , "");
|
Intent.printIntentArgsHelp(pw , "");
|
||||||
|
|||||||
146
services/core/java/com/android/server/pm/SilentUpdatePolicy.java
Normal file
146
services/core/java/com/android/server/pm/SilentUpdatePolicy.java
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks for the installer package name and installing app package name of silent updates.
|
||||||
|
* This class is used to throttle repeated silent updates of the same installer and application
|
||||||
|
* in the {@link PackageInstallerSession}.
|
||||||
|
*/
|
||||||
|
public class SilentUpdatePolicy {
|
||||||
|
// A throttle time to prevent the installer from silently updating the same app repeatedly.
|
||||||
|
private static final long SILENT_UPDATE_THROTTLE_TIME_MS = TimeUnit.SECONDS.toMillis(30);
|
||||||
|
|
||||||
|
// Map to the uptime timestamp for each installer and app of the silent update.
|
||||||
|
@GuardedBy("mSilentUpdateInfos")
|
||||||
|
private final ArrayMap<Pair<String, String>, Long> mSilentUpdateInfos = new ArrayMap<>();
|
||||||
|
|
||||||
|
// An installer allowed for the unlimited silent updates within the throttle time
|
||||||
|
@GuardedBy("mSilentUpdateInfos")
|
||||||
|
private String mAllowUnlimitedSilentUpdatesInstaller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the silent update is allowed by the given installer and app package name.
|
||||||
|
*
|
||||||
|
* @param installerPackageName The installer package name to check
|
||||||
|
* @param packageName The package name which is installing
|
||||||
|
* @return true if the silent update is allowed.
|
||||||
|
*/
|
||||||
|
public boolean isSilentUpdateAllowed(@Nullable String installerPackageName,
|
||||||
|
@NonNull String packageName) {
|
||||||
|
if (installerPackageName == null) {
|
||||||
|
// Always true for the installer from Shell
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
final long lastSilentUpdatedMs = getTimestampMs(installerPackageName, packageName);
|
||||||
|
return SystemClock.uptimeMillis() - lastSilentUpdatedMs > SILENT_UPDATE_THROTTLE_TIME_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding track for the installer package name and installing app of a silent update. This is
|
||||||
|
* used to determine whether a silent update is allowed.
|
||||||
|
*
|
||||||
|
* @param installerPackageName The installer package name
|
||||||
|
* @param packageName The package name which is installing
|
||||||
|
*/
|
||||||
|
public void track(@Nullable String installerPackageName, @NonNull String packageName) {
|
||||||
|
if (installerPackageName == null) {
|
||||||
|
// No need to track the installer from Shell.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (mSilentUpdateInfos) {
|
||||||
|
if (mAllowUnlimitedSilentUpdatesInstaller != null
|
||||||
|
&& mAllowUnlimitedSilentUpdatesInstaller.equals(installerPackageName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final long uptime = SystemClock.uptimeMillis();
|
||||||
|
pruneLocked(uptime);
|
||||||
|
|
||||||
|
final Pair<String, String> key = Pair.create(installerPackageName, packageName);
|
||||||
|
mSilentUpdateInfos.put(key, uptime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an installer to allow for the unlimited silent updates. Reset the tracker if the
|
||||||
|
* installer package name is <code>null</code>.
|
||||||
|
*/
|
||||||
|
void setAllowUnlimitedSilentUpdates(@Nullable String installerPackageName) {
|
||||||
|
synchronized (mSilentUpdateInfos) {
|
||||||
|
if (installerPackageName == null) {
|
||||||
|
mSilentUpdateInfos.clear();
|
||||||
|
}
|
||||||
|
mAllowUnlimitedSilentUpdatesInstaller = installerPackageName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pruneLocked(long uptime) {
|
||||||
|
final int size = mSilentUpdateInfos.size();
|
||||||
|
for (int i = size - 1; i >= 0; i--) {
|
||||||
|
final long lastSilentUpdatedMs = mSilentUpdateInfos.valueAt(i);
|
||||||
|
if (uptime - lastSilentUpdatedMs > SILENT_UPDATE_THROTTLE_TIME_MS) {
|
||||||
|
mSilentUpdateInfos.removeAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timestamp by the given installer and app package name. {@code -1} is returned if not
|
||||||
|
* exist.
|
||||||
|
*/
|
||||||
|
private long getTimestampMs(@NonNull String installerPackageName, @NonNull String packageName) {
|
||||||
|
final Pair<String, String> key = Pair.create(installerPackageName, packageName);
|
||||||
|
final Long timestampMs;
|
||||||
|
synchronized (mSilentUpdateInfos) {
|
||||||
|
timestampMs = mSilentUpdateInfos.get(key);
|
||||||
|
}
|
||||||
|
return timestampMs != null ? timestampMs : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump(IndentingPrintWriter pw) {
|
||||||
|
synchronized (mSilentUpdateInfos) {
|
||||||
|
if (mSilentUpdateInfos.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pw.println("Last silent updated Infos:");
|
||||||
|
pw.increaseIndent();
|
||||||
|
final int size = mSilentUpdateInfos.size();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
final Pair<String, String> key = mSilentUpdateInfos.keyAt(i);
|
||||||
|
if (key == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pw.printPair("installerPackageName", key.first);
|
||||||
|
pw.printPair("packageName", key.second);
|
||||||
|
pw.printPair("silentUpdatedMillis", mSilentUpdateInfos.valueAt(i));
|
||||||
|
pw.println();
|
||||||
|
}
|
||||||
|
pw.decreaseIndent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,20 @@
|
|||||||
|
|
||||||
package com.android.server.pm;
|
package com.android.server.pm;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.testng.Assert.assertThrows;
|
||||||
|
|
||||||
import android.apex.ApexSessionInfo;
|
import android.apex.ApexSessionInfo;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.IntentSender;
|
import android.content.IntentSender;
|
||||||
@@ -32,8 +46,6 @@ import com.android.internal.content.PackageHelper;
|
|||||||
import com.android.internal.os.BackgroundThread;
|
import com.android.internal.os.BackgroundThread;
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@@ -52,18 +64,6 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
|
||||||
import static org.mockito.Mockito.doAnswer;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
|
||||||
import static org.mockito.Mockito.never;
|
|
||||||
import static org.mockito.Mockito.spy;
|
|
||||||
import static org.mockito.Mockito.times;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
import static org.testng.Assert.assertThrows;
|
|
||||||
|
|
||||||
@Presubmit
|
@Presubmit
|
||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
public class StagingManagerTest {
|
public class StagingManagerTest {
|
||||||
@@ -472,6 +472,7 @@ public class StagingManagerTest {
|
|||||||
/* context */ null,
|
/* context */ null,
|
||||||
/* pm */ null,
|
/* pm */ null,
|
||||||
/* sessionProvider */ null,
|
/* sessionProvider */ null,
|
||||||
|
/* silentUpdatePolicy */ null,
|
||||||
/* looper */ BackgroundThread.getHandler().getLooper(),
|
/* looper */ BackgroundThread.getHandler().getLooper(),
|
||||||
/* stagingManager */ null,
|
/* stagingManager */ null,
|
||||||
/* sessionId */ sessionId,
|
/* sessionId */ sessionId,
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ import android.util.AtomicFile;
|
|||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.TypedXmlPullParser;
|
import android.util.TypedXmlPullParser;
|
||||||
import android.util.TypedXmlSerializer;
|
import android.util.TypedXmlSerializer;
|
||||||
import android.util.TypedXmlPullParser;
|
|
||||||
import android.util.TypedXmlSerializer;
|
|
||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
|
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
@@ -165,6 +163,7 @@ public class PackageInstallerSessionTest {
|
|||||||
/* context */null,
|
/* context */null,
|
||||||
/* pm */ mMockPackageManagerInternal,
|
/* pm */ mMockPackageManagerInternal,
|
||||||
/* sessionProvider */ null,
|
/* sessionProvider */ null,
|
||||||
|
/* silentUpdatePolicy */ null,
|
||||||
/* looper */ BackgroundThread.getHandler().getLooper(),
|
/* looper */ BackgroundThread.getHandler().getLooper(),
|
||||||
/* stagingManager */ null,
|
/* stagingManager */ null,
|
||||||
/* sessionId */ sessionId,
|
/* sessionId */ sessionId,
|
||||||
@@ -239,7 +238,7 @@ public class PackageInstallerSessionTest {
|
|||||||
session = PackageInstallerSession.readFromXml(in, null,
|
session = PackageInstallerSession.readFromXml(in, null,
|
||||||
null, mMockPackageManagerInternal,
|
null, mMockPackageManagerInternal,
|
||||||
BackgroundThread.getHandler().getLooper(), null,
|
BackgroundThread.getHandler().getLooper(), null,
|
||||||
mTmpDir, null);
|
mTmpDir, null, null);
|
||||||
ret.add(session);
|
ret.add(session);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Slog.e("PackageInstallerSessionTest", "Exception ", e);
|
Slog.e("PackageInstallerSessionTest", "Exception ", e);
|
||||||
|
|||||||
Reference in New Issue
Block a user