Merge "Remove broken code for mounting encrypted OBB files"
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 40beab3..aebc5e8 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -33,6 +33,9 @@
import com.android.internal.annotations.GuardedBy;
+import java.io.PrintWriter;
+import java.time.Duration;
+import java.time.Instant;
import java.util.Objects;
import java.util.function.Supplier;
@@ -96,8 +99,8 @@
@Override
public String toString() {
return "TimeResult{"
- + "mTimeMillis=" + mTimeMillis
- + ", mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
+ + "mTimeMillis=" + Instant.ofEpochMilli(mTimeMillis)
+ + ", mElapsedRealtimeMillis=" + Duration.ofMillis(mElapsedRealtimeMillis)
+ ", mCertaintyMillis=" + mCertaintyMillis
+ '}';
}
@@ -131,6 +134,14 @@
}
};
+ /** An in-memory config override for use during tests. */
+ @Nullable
+ private String mHostnameForTests;
+
+ /** An in-memory config override for use during tests. */
+ @Nullable
+ private Duration mTimeoutForTests;
+
// Declared volatile and accessed outside of synchronized blocks to avoid blocking reads during
// forceRefresh().
private volatile TimeResult mTimeResult;
@@ -148,12 +159,23 @@
return sSingleton;
}
+ /**
+ * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
+ * test value, i.e. so the normal value will be used next time.
+ */
+ public void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+ synchronized (this) {
+ mHostnameForTests = hostname;
+ mTimeoutForTests = timeout;
+ }
+ }
+
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public boolean forceRefresh() {
synchronized (this) {
NtpConnectionInfo connectionInfo = getNtpConnectionInfo();
if (connectionInfo == null) {
- // missing server config, so no trusted time available
+ // missing server config, so no NTP time available
if (LOGD) Log.d(TAG, "forceRefresh: invalid server config");
return false;
}
@@ -290,6 +312,14 @@
int getTimeoutMillis() {
return mTimeoutMillis;
}
+
+ @Override
+ public String toString() {
+ return "NtpConnectionInfo{"
+ + "mServer='" + mServer + '\''
+ + ", mTimeoutMillis=" + mTimeoutMillis
+ + '}';
+ }
}
@GuardedBy("this")
@@ -297,17 +327,41 @@
final ContentResolver resolver = mContext.getContentResolver();
final Resources res = mContext.getResources();
- final String defaultServer = res.getString(
- com.android.internal.R.string.config_ntpServer);
- final int defaultTimeoutMillis = res.getInteger(
- com.android.internal.R.integer.config_ntpTimeout);
- final String secureServer = Settings.Global.getString(
- resolver, Settings.Global.NTP_SERVER);
- final int timeoutMillis = Settings.Global.getInt(
- resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis);
+ final String hostname;
+ if (mHostnameForTests != null) {
+ hostname = mHostnameForTests;
+ } else {
+ String serverGlobalSetting =
+ Settings.Global.getString(resolver, Settings.Global.NTP_SERVER);
+ if (serverGlobalSetting != null) {
+ hostname = serverGlobalSetting;
+ } else {
+ hostname = res.getString(com.android.internal.R.string.config_ntpServer);
+ }
+ }
- final String server = secureServer != null ? secureServer : defaultServer;
- return TextUtils.isEmpty(server) ? null : new NtpConnectionInfo(server, timeoutMillis);
+ final int timeoutMillis;
+ if (mTimeoutForTests != null) {
+ timeoutMillis = (int) mTimeoutForTests.toMillis();
+ } else {
+ int defaultTimeoutMillis =
+ res.getInteger(com.android.internal.R.integer.config_ntpTimeout);
+ timeoutMillis = Settings.Global.getInt(
+ resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis);
+ }
+ return TextUtils.isEmpty(hostname) ? null : new NtpConnectionInfo(hostname, timeoutMillis);
+ }
+
+ /** Prints debug information. */
+ public void dump(PrintWriter pw) {
+ synchronized (this) {
+ pw.println("getNtpConnectionInfo()=" + getNtpConnectionInfo());
+ pw.println("mTimeResult=" + mTimeResult);
+ if (mTimeResult != null) {
+ pw.println("mTimeResult.getAgeMillis()="
+ + Duration.ofMillis(mTimeResult.getAgeMillis()));
+ }
+ }
}
}
diff --git a/core/res/OWNERS b/core/res/OWNERS
index e241dd6..b7df255 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -25,6 +25,10 @@
tsuji@google.com
yamasani@google.com
+# Resources finalization
+per-file res/xml/public-staging.xml = file:/tools/aapt2/OWNERS
+per-file res/xml/public-final.xml = file:/tools/aapt2/OWNERS
+
# Multiuser
per-file res/xml/config_user_types.xml = file:/MULTIUSER_OWNERS
diff --git a/identity/java/android/security/identity/CredentialDataRequest.java b/identity/java/android/security/identity/CredentialDataRequest.java
index 2a47a02..3482384 100644
--- a/identity/java/android/security/identity/CredentialDataRequest.java
+++ b/identity/java/android/security/identity/CredentialDataRequest.java
@@ -153,7 +153,15 @@
/**
* Sets whether to allow using an authentication key which use count has been exceeded.
*
- * By default this is set to true.
+ * <p>This is useful in situations where the application hasn't had a chance to renew
+ * authentication keys, for example if the device hasn't been connected to the Internet or
+ * if the issuing authority server has been down.
+ *
+ * <p>The reason this could be useful is that the privacy risk of reusing an authentication
+ * key for a credential presentation could be significantly smaller compared to the
+ * inconvenience of not being able to present the credential at all.
+ *
+ * <p>By default this is set to true.
*
* @param allowUsingExhaustedKeys whether to allow using an authentication key which use
* count has been exceeded if no other key is available.
@@ -167,7 +175,16 @@
/**
* Sets whether to allow using an authentication key which is expired.
*
- * By default this is set to false.
+ * <p>This is useful in situations where the application hasn't had a chance to renew
+ * authentication keys, for example if the device hasn't been connected to the Internet or
+ * if the issuing authority server has been down.
+ *
+ * <p>The reason this could be useful is that many verifiers are likely to accept a
+ * credential presentation using an expired authentication key (the credential itself
+ * wouldn't be expired) and it's likely better for the holder to be able to do this than
+ * not present their credential at all.
+ *
+ * <p>By default this is set to false.
*
* @param allowUsingExpiredKeys whether to allow using an authentication key which is
* expired if no other key is available.
@@ -181,7 +198,12 @@
/**
* Sets whether to increment the use-count for the authentication key used.
*
- * By default this is set to true.
+ * <p>Not incrementing the use-count for an authentication key is useful in situations
+ * where the authentication key is known with certainty to not be leaked. For example,
+ * consider an application doing a credential presentation for the sole purpose of
+ * displaying the credential data to the user (not for verification).
+ *
+ * <p>By default this is set to true.
*
* @param incrementUseCount whether to increment the use count of the authentication
* key used.
diff --git a/identity/java/android/security/identity/PresentationSession.java b/identity/java/android/security/identity/PresentationSession.java
index afaafce..6cde611 100644
--- a/identity/java/android/security/identity/PresentationSession.java
+++ b/identity/java/android/security/identity/PresentationSession.java
@@ -26,6 +26,9 @@
/**
* Class for presenting multiple documents to a remote verifier.
*
+ * <p>This should be used for all interactions with a remote verifier instead of the now deprecated
+ * {@link IdentityCredential#getEntries(byte[], Map, byte[], byte[])} method.
+ *
* Use {@link IdentityCredentialStore#createPresentationSession(int)} to create a {@link
* PresentationSession} instance.
*/
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 1e534b7..186ff62 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.timedetector.NetworkTimeSuggestion;
@@ -45,12 +46,12 @@
import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.NtpTrustedTime.TimeResult;
-import android.util.TimeUtils;
import com.android.internal.util.DumpUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.time.Duration;
/**
* Monitors the network time. If looking up the network time fails for some reason, it tries a few
@@ -191,6 +192,19 @@
return success;
}
+ /**
+ * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
+ * test value, i.e. so the normal value will be used next time.
+ */
+ void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.SET_TIME, "set NTP server config for tests");
+
+ mLocalLog.log("Setting server config for tests: hostname=" + hostname
+ + ", timeout=" + timeout);
+ mTime.setServerConfigForTests(hostname, timeout);
+ }
+
private void onPollNetworkTime(int event) {
// If we don't have any default network, don't bother.
if (mDefaultNetwork == null) return;
@@ -349,17 +363,14 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
- pw.print("PollingIntervalMs: ");
- TimeUtils.formatDuration(mPollingIntervalMs, pw);
- pw.print("\nPollingIntervalShorterMs: ");
- TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
- pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
- pw.println("\nTryAgainCounter: " + mTryAgainCounter);
- NtpTrustedTime.TimeResult ntpResult = mTime.getCachedTimeResult();
- pw.println("NTP cache result: " + ntpResult);
- if (ntpResult != null) {
- pw.println("NTP result age: " + ntpResult.getAgeMillis());
- }
+ pw.println("mPollingIntervalMs=" + Duration.ofMillis(mPollingIntervalMs));
+ pw.println("mPollingIntervalShorterMs=" + Duration.ofMillis(mPollingIntervalShorterMs));
+ pw.println("mTryAgainTimesMax=" + mTryAgainTimesMax);
+ pw.println("mTryAgainCounter=" + mTryAgainCounter);
+ pw.println();
+ pw.println("NtpTrustedTime:");
+ mTime.dump(pw);
+ pw.println();
pw.println("Local logs:");
mLocalLog.dump(fd, pw, args);
pw.println();
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
index dc93023..464af01 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
@@ -20,6 +20,7 @@
import android.os.ShellCommand;
import java.io.PrintWriter;
+import java.time.Duration;
import java.util.Objects;
/** Implements the shell command interface for {@link NetworkTimeUpdateService}. */
@@ -40,6 +41,13 @@
*/
private static final String SHELL_COMMAND_FORCE_REFRESH = "force_refresh";
+ /**
+ * A shell command that sets the NTP server config for tests. Config is cleared on reboot.
+ */
+ private static final String SHELL_COMMAND_SET_SERVER_CONFIG = "set_server_config";
+ private static final String SET_SERVER_CONFIG_HOSTNAME_ARG = "--hostname";
+ private static final String SET_SERVER_CONFIG_TIMEOUT_ARG = "--timeout_millis";
+
@NonNull
private final NetworkTimeUpdateService mNetworkTimeUpdateService;
@@ -58,6 +66,8 @@
return runClearTime();
case SHELL_COMMAND_FORCE_REFRESH:
return runForceRefresh();
+ case SHELL_COMMAND_SET_SERVER_CONFIG:
+ return runSetServerConfig();
default: {
return handleDefaultCommands(cmd);
}
@@ -75,6 +85,29 @@
return 0;
}
+ private int runSetServerConfig() {
+ String hostname = null;
+ Duration timeout = null;
+ String opt;
+ while ((opt = getNextArg()) != null) {
+ switch (opt) {
+ case SET_SERVER_CONFIG_HOSTNAME_ARG: {
+ hostname = getNextArgRequired();
+ break;
+ }
+ case SET_SERVER_CONFIG_TIMEOUT_ARG: {
+ timeout = Duration.ofMillis(Integer.parseInt(getNextArgRequired()));
+ break;
+ }
+ default: {
+ throw new IllegalArgumentException("Unknown option: " + opt);
+ }
+ }
+ }
+ mNetworkTimeUpdateService.setServerConfigForTests(hostname, timeout);
+ return 0;
+ }
+
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
@@ -85,6 +118,12 @@
pw.printf(" Clears the latest time.\n");
pw.printf(" %s\n", SHELL_COMMAND_FORCE_REFRESH);
pw.printf(" Refreshes the latest time. Prints whether it was successful.\n");
+ pw.printf(" %s\n", SHELL_COMMAND_SET_SERVER_CONFIG);
+ pw.printf(" Sets the NTP server config for tests. The config is not persisted.\n");
+ pw.printf(" Options: [%s <hostname>] [%s <millis>]\n",
+ SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_TIMEOUT_ARG);
+ pw.printf(" Each key/value is optional and must be specified to override the\n");
+ pw.printf(" normal value, not specifying a key causes it to reset to the original.\n");
pw.println();
}
}
diff --git a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
index 62b701a..11c451e 100644
--- a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
+++ b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.content.ClipData;
+import android.os.SystemProperties;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -39,6 +40,8 @@
private static final String PIPE_NAME = "pipe:clipboard";
private static final int HOST_PORT = 5000;
private final Thread mHostMonitorThread;
+ private static final boolean LOG_CLIBOARD_ACCESS =
+ SystemProperties.getBoolean("ro.boot.qemu.log_clipboard_access", false);
private FileDescriptor mPipe = null;
private static byte[] createOpenHandshake() {
@@ -132,6 +135,9 @@
new String[]{"text/plain"},
new ClipData.Item(str));
+ if (LOG_CLIBOARD_ACCESS) {
+ Slog.i(TAG, "Setting the guest clipboard to '" + str + "'");
+ }
setAndroidClipboard.accept(clip);
} catch (ErrnoException | InterruptedIOException e) {
closePipe();
@@ -156,6 +162,10 @@
}
private void setHostClipboardImpl(final String value) {
+ if (LOG_CLIBOARD_ACCESS) {
+ Slog.i(TAG, "Setting the host clipboard to '" + value + "'");
+ }
+
try {
if (isPipeOpened()) {
sendMessage(value.getBytes());
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 9f58f65..0a77430 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -991,10 +991,10 @@
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(ACTION_PACKAGE_ADDED);
packageFilter.addDataScheme("package");
- mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
+ mContext.registerReceiverForAllUsers(mPackageReceiver, packageFilter, null, mHandler);
// listen for UID changes to update policy
- mContext.registerReceiver(
+ mContext.registerReceiverForAllUsers(
mUidRemovedReceiver, new IntentFilter(ACTION_UID_REMOVED), null, mHandler);
// listen for user changes to update policy
diff --git a/services/tests/wmtests/src/com/android/server/policy/OWNERS b/services/tests/wmtests/src/com/android/server/policy/OWNERS
new file mode 100644
index 0000000..27891dc
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/policy/OWNERS
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 741f33f..87c75be 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -267,7 +267,8 @@
@Test
public void testUpdateSleep() {
doCallRealMethod().when(mWm.mRoot).hasAwakeDisplay();
- mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
+ mSupervisor.mGoingToSleepWakeLock =
+ mSystemServicesTestRule.createStubbedWakeLock(true /* needVerification */);
final Task rootHomeTask = mWm.mRoot.getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
final ActivityRecord homeActivity = new ActivityBuilder(mAtm).setTask(rootHomeTask).build();
final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 8e7ba4bc..0b2399b1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -102,6 +102,10 @@
static int sNextTaskId = 100;
private static final int[] TEST_USER_PROFILE_IDS = {};
+ /** Use a real static object so there won't be NPE in finalize() after clearInlineMocks(). */
+ private static final PowerManager.WakeLock sWakeLock = getInstrumentation().getContext()
+ .getSystemService(PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ private PowerManager.WakeLock mStubbedWakeLock;
private Description mDescription;
private Context mContext;
@@ -196,7 +200,8 @@
// Prevent "WakeLock finalized while still held: SCREEN_FROZEN".
final PowerManager pm = mock(PowerManager.class);
doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
- doReturn(mock(PowerManager.WakeLock.class)).when(pm).newWakeLock(anyInt(), anyString());
+ mStubbedWakeLock = createStubbedWakeLock(false /* needVerification */);
+ doReturn(mStubbedWakeLock).when(pm).newWakeLock(anyInt(), anyString());
// DisplayManagerInternal
final DisplayManagerInternal dmi = mock(DisplayManagerInternal.class);
@@ -403,6 +408,16 @@
return mPowerManagerWrapper;
}
+ /** Creates a no-op wakelock object. */
+ PowerManager.WakeLock createStubbedWakeLock(boolean needVerification) {
+ if (needVerification) {
+ return mock(PowerManager.WakeLock.class, Mockito.withSettings()
+ .spiedInstance(sWakeLock).defaultAnswer(Mockito.RETURNS_DEFAULTS));
+ }
+ return mock(PowerManager.WakeLock.class, Mockito.withSettings()
+ .spiedInstance(sWakeLock).stubOnly());
+ }
+
void setSurfaceFactory(Supplier<Surface> factory) {
mSurfaceFactory = factory;
}
@@ -558,7 +573,7 @@
// unit test version does not handle launch wake lock
doNothing().when(this).acquireLaunchWakelock();
- mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class);
+ mLaunchingActivityWakeLock = mStubbedWakeLock;
initialize();