summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java7
-rw-r--r--cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java2
-rw-r--r--cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java2
-rw-r--r--cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java2
-rw-r--r--core/java/android/accounts/AbstractAccountAuthenticator.java8
-rw-r--r--core/java/android/os/Binder.java8
-rw-r--r--core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java6
-rw-r--r--core/java/com/android/internal/expresslog/Counter.java47
-rw-r--r--core/jni/Android.bp5
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/com_android_internal_expresslog_Counter.cpp57
-rw-r--r--core/res/res/values/config.xml16
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--keystore/java/android/security/keystore/KeyProperties.java46
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java5
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java17
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/qrcode/QrDecorateView.java45
-rw-r--r--services/core/java/com/android/server/VpnManagerService.java4
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java79
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java2
-rw-r--r--services/core/java/com/android/server/pm/dex/OdsignStatsLogger.java46
-rw-r--r--services/core/java/com/android/server/rollback/README.md58
-rw-r--r--services/core/java/com/android/server/wm/RunningTasks.java111
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java100
25 files changed, 484 insertions, 196 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
index b6361ce56569..80a70a6e9e9e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
@@ -31,6 +31,7 @@ import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.expresslog.Counter;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
@@ -88,6 +89,8 @@ public final class TimeController extends StateController {
// will never be unsatisfied (our time base can not go backwards).
final long nowElapsedMillis = sElapsedRealtimeClock.millis();
if (job.hasDeadlineConstraint() && evaluateDeadlineConstraint(job, nowElapsedMillis)) {
+ // We're intentionally excluding jobs whose deadlines have passed
+ // (mostly like deadlines of 0) when the job was scheduled.
return;
} else if (job.hasTimingDelayConstraint() && evaluateTimingDelayConstraint(job,
nowElapsedMillis)) {
@@ -159,6 +162,8 @@ public final class TimeController extends StateController {
// Scheduler.
mStateChangedListener.onRunJobNow(job);
}
+ Counter.logIncrement(
+ "job_scheduler.value_job_scheduler_job_deadline_expired_counter");
} else if (wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_DEADLINE)) {
// This job's deadline is earlier than the current set alarm. Update the alarm.
setDeadlineExpiredAlarmLocked(job.getLatestRunTimeElapsed(),
@@ -229,6 +234,8 @@ public final class TimeController extends StateController {
// Scheduler.
mStateChangedListener.onRunJobNow(job);
}
+ Counter.logIncrement(
+ "job_scheduler.value_job_scheduler_job_deadline_expired_counter");
it.remove();
} else { // Sorted by expiry time, so take the next one and stop.
if (!wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_DEADLINE)) {
diff --git a/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java b/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
index 3b14be7327f7..24727c5f2448 100644
--- a/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
+++ b/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
@@ -107,7 +107,7 @@ public class DumpCommand extends Command {
DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
int rotation = display.getRotation();
Point size = new Point();
- display.getSize(size);
+ display.getRealSize(size);
AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile, rotation, size.x,
size.y);
}
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
index ab198b319e27..488292d68620 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
@@ -139,7 +139,7 @@ public class AccessibilityNodeInfoDumper {
serializer.attribute("", "id", Integer.toString(displayId));
int rotation = display.getRotation();
Point size = new Point();
- display.getSize(size);
+ display.getRealSize(size);
for (int i = 0, n = windows.size(); i < n; ++i) {
dumpWindowRec(windows.get(i), serializer, i, size.x, size.y, rotation);
}
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
index 6fd2bf250e2c..1bcd343e5668 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiDevice.java
@@ -767,7 +767,7 @@ public class UiDevice {
if(root != null) {
Display display = getAutomatorBridge().getDefaultDisplay();
Point size = new Point();
- display.getSize(size);
+ display.getRealSize(size);
AccessibilityNodeInfoDumper.dumpWindowToFile(root,
new File(new File(Environment.getDataDirectory(), "local/tmp"), fileName),
display.getRotation(), size.x, size.y);
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index 3807b503ce70..2f32fa4216f1 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -120,27 +120,27 @@ public abstract class AbstractAccountAuthenticator {
/**
* Bundle key used for the {@link String} account type in session bundle.
* This is used in the default implementation of
- * {@link #startAddAccountSession} and {@link startUpdateCredentialsSession}.
+ * {@link #startAddAccountSession} and {@link #startUpdateCredentialsSession}.
*/
private static final String KEY_AUTH_TOKEN_TYPE =
"android.accounts.AbstractAccountAuthenticato.KEY_AUTH_TOKEN_TYPE";
/**
* Bundle key used for the {@link String} array of required features in
* session bundle. This is used in the default implementation of
- * {@link #startAddAccountSession} and {@link startUpdateCredentialsSession}.
+ * {@link #startAddAccountSession} and {@link #startUpdateCredentialsSession}.
*/
private static final String KEY_REQUIRED_FEATURES =
"android.accounts.AbstractAccountAuthenticator.KEY_REQUIRED_FEATURES";
/**
* Bundle key used for the {@link Bundle} options in session bundle. This is
* used in default implementation of {@link #startAddAccountSession} and
- * {@link startUpdateCredentialsSession}.
+ * {@link #startUpdateCredentialsSession}.
*/
private static final String KEY_OPTIONS =
"android.accounts.AbstractAccountAuthenticator.KEY_OPTIONS";
/**
* Bundle key used for the {@link Account} account in session bundle. This is used
- * used in default implementation of {@link startUpdateCredentialsSession}.
+ * used in default implementation of {@link #startUpdateCredentialsSession}.
*/
private static final String KEY_ACCOUNT =
"android.accounts.AbstractAccountAuthenticator.KEY_ACCOUNT";
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 6d5c741e7dc7..3d10661062ea 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -911,11 +911,15 @@ public class Binder implements IBinder {
final String transactionName = getTransactionName(transactionCode);
final StringBuffer buf = new StringBuffer();
+ // Keep trace name consistent with cpp trace name in:
+ // system/tools/aidl/generate_cpp.cpp
+ buf.append("AIDL::java::");
if (transactionName != null) {
- buf.append(mSimpleDescriptor).append(":").append(transactionName);
+ buf.append(mSimpleDescriptor).append("::").append(transactionName);
} else {
- buf.append(mSimpleDescriptor).append("#").append(transactionCode);
+ buf.append(mSimpleDescriptor).append("::#").append(transactionCode);
}
+ buf.append("::server");
transactionTraceName = buf.toString();
mTransactionTraceNames.setRelease(index, transactionTraceName);
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index c8c1fd4eba21..eb467e0dcc38 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -93,8 +93,9 @@ public class ApkSignatureSchemeV2Verifier {
* associated with each signer.
*
* @throws SignatureNotFoundException if the APK is not signed using APK Signature Scheme v2.
- * @throws SecurityException if a APK Signature Scheme v2 signature of this APK does not verify.
- * @throws IOException if an I/O error occurs while reading the APK file.
+ * @throws SecurityException if an APK Signature Scheme v2 signature of this APK does
+ * not verify.
+ * @throws IOException if an I/O error occurs while reading the APK file.
*/
public static X509Certificate[][] verify(String apkFile)
throws SignatureNotFoundException, SecurityException, IOException {
@@ -386,7 +387,6 @@ public class ApkSignatureSchemeV2Verifier {
break;
}
}
- return;
}
static byte[] getVerityRootHash(String apkPath)
diff --git a/core/java/com/android/internal/expresslog/Counter.java b/core/java/com/android/internal/expresslog/Counter.java
new file mode 100644
index 000000000000..7571073a9822
--- /dev/null
+++ b/core/java/com/android/internal/expresslog/Counter.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 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.internal.expresslog;
+
+import android.annotation.NonNull;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+/** Counter encapsulates StatsD write API calls */
+public final class Counter {
+
+ // Not instantiable.
+ private Counter() {}
+
+ /**
+ * Increments Telemetry Express Counter metric by 1
+ * @hide
+ */
+ public static void logIncrement(@NonNull String metricId) {
+ logIncrement(metricId, 1);
+ }
+
+ /**
+ * Increments Telemetry Express Counter metric by arbitrary value
+ * @hide
+ */
+ public static void logIncrement(@NonNull String metricId, long amount) {
+ final long metricIdHash = hashString(metricId);
+ FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_EVENT_REPORTED, metricIdHash, amount);
+ }
+
+ private static native long hashString(String stringToHash);
+}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index e032fa2d5547..7cd7d2957d25 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -34,6 +34,8 @@ cc_library_shared {
"-Wno-error=deprecated-declarations",
"-Wunused",
"-Wunreachable-code",
+
+ "-DNAMESPACE_FOR_HASH_FUNCTIONS=farmhash",
],
cppflags: ["-Wno-conversion-null"],
@@ -211,6 +213,7 @@ cc_library_shared {
"android_content_res_Configuration.cpp",
"android_security_Scrypt.cpp",
"com_android_internal_content_om_OverlayConfig.cpp",
+ "com_android_internal_expresslog_Counter.cpp",
"com_android_internal_net_NetworkUtilsInternal.cpp",
"com_android_internal_os_ClassLoaderFactory.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
@@ -244,6 +247,7 @@ cc_library_shared {
"libscrypt_static",
"libstatssocket_lazy",
"libskia",
+ "libtextclassifier_hash_static",
],
shared_libs: [
@@ -326,6 +330,7 @@ cc_library_shared {
header_libs: [
"bionic_libc_platform_headers",
"dnsproxyd_protocol_headers",
+ "libtextclassifier_hash_headers",
],
},
host: {
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 6a051c39cab0..6b736488fe8b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -193,6 +193,7 @@ extern int register_android_security_Scrypt(JNIEnv *env);
extern int register_com_android_internal_content_F2fsUtils(JNIEnv* env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
+extern int register_com_android_internal_expresslog_Counter(JNIEnv* env);
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
@@ -1584,6 +1585,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_os_SharedMemory),
REG_JNI(register_android_os_incremental_IncrementalManager),
REG_JNI(register_com_android_internal_content_om_OverlayConfig),
+ REG_JNI(register_com_android_internal_expresslog_Counter),
REG_JNI(register_com_android_internal_net_NetworkUtilsInternal),
REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
REG_JNI(register_com_android_internal_os_LongArrayMultiStateCounter),
diff --git a/core/jni/com_android_internal_expresslog_Counter.cpp b/core/jni/com_android_internal_expresslog_Counter.cpp
new file mode 100644
index 000000000000..d4a8c23b8343
--- /dev/null
+++ b/core/jni/com_android_internal_expresslog_Counter.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include <nativehelper/JNIHelp.h>
+#include <utils/hash/farmhash.h>
+
+#include "core_jni_helpers.h"
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+static jclass g_stringClass = nullptr;
+
+/**
+ * Class: com_android_internal_expresslog_Counter
+ * Method: hashString
+ * Signature: (Ljava/lang/String;)J
+ */
+static jlong hashString(JNIEnv* env, jclass /*class*/, jstring metricNameObj) {
+ ScopedUtfChars name(env, metricNameObj);
+ if (name.c_str() == nullptr) {
+ return 0;
+ }
+
+ return static_cast<jlong>(farmhash::Fingerprint64(name.c_str(), name.size()));
+}
+
+static const JNINativeMethod g_methods[] = {
+ {"hashString", "(Ljava/lang/String;)J", (void*)hashString},
+};
+
+static const char* const kCounterPathName = "com/android/internal/expresslog/Counter";
+
+namespace android {
+
+int register_com_android_internal_expresslog_Counter(JNIEnv* env) {
+ jclass stringClass = FindClassOrDie(env, "java/lang/String");
+ g_stringClass = MakeGlobalRefOrDie(env, stringClass);
+
+ return RegisterMethodsOrDie(env, kCounterPathName, g_methods, NELEM(g_methods));
+}
+
+} // namespace android
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index cf1050461d68..343bc1cf11db 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -342,22 +342,6 @@
<!-- Mask to use when checking skb mark defined in config_networkWakeupPacketMark above. -->
<integer name="config_networkWakeupPacketMask">0</integer>
- <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames
- Those frames are identified by the field Eth-type having values
- less than 0x600 -->
- <bool translatable="false" name="config_apfDrop802_3Frames">true</bool>
-
- <!-- An array of Denylisted EtherType, packets with EtherTypes within this array
- will be dropped
- TODO: need to put proper values, these are for testing purposes only -->
- <integer-array translatable="false" name="config_apfEthTypeBlackList">
- <item>0x88A2</item>
- <item>0x88A4</item>
- <item>0x88B8</item>
- <item>0x88CD</item>
- <item>0x88E3</item>
- </integer-array>
-
<!-- Default value for ConnectivityManager.getMultipathPreference() on metered networks. Actual
device behaviour is controlled by Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE.
This is the default value of that setting. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1f71bf9f95dd..7736c1ac2c2f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2016,8 +2016,6 @@
<java-symbol type="integer" name="config_networkAvoidBadWifi" />
<java-symbol type="integer" name="config_networkWakeupPacketMark" />
<java-symbol type="integer" name="config_networkWakeupPacketMask" />
- <java-symbol type="bool" name="config_apfDrop802_3Frames" />
- <java-symbol type="array" name="config_apfEthTypeBlackList" />
<java-symbol type="integer" name="config_networkDefaultDailyMultipathQuotaBytes" />
<java-symbol type="integer" name="config_networkMeteredMultipathPreference" />
<java-symbol type="array" name="config_networkSupportedKeepaliveCount" />
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index dbd918e35d70..62455988db34 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -30,6 +30,7 @@ import libcore.util.EmptyArray;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECParameterSpec;
import java.security.spec.MGF1ParameterSpec;
import java.util.Collection;
import java.util.Locale;
@@ -914,6 +915,51 @@ public abstract class KeyProperties {
}
/**
+ * @hide
+ */
+ public abstract static class EcCurve {
+ private EcCurve() {}
+
+ /**
+ * @hide
+ */
+ public static int toKeymasterCurve(ECParameterSpec spec) {
+ int keySize = spec.getCurve().getField().getFieldSize();
+ switch (keySize) {
+ case 224:
+ return android.hardware.security.keymint.EcCurve.P_224;
+ case 256:
+ return android.hardware.security.keymint.EcCurve.P_256;
+ case 384:
+ return android.hardware.security.keymint.EcCurve.P_384;
+ case 521:
+ return android.hardware.security.keymint.EcCurve.P_521;
+ default:
+ return -1;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public static int fromKeymasterCurve(int ecCurve) {
+ switch (ecCurve) {
+ case android.hardware.security.keymint.EcCurve.P_224:
+ return 224;
+ case android.hardware.security.keymint.EcCurve.P_256:
+ case android.hardware.security.keymint.EcCurve.CURVE_25519:
+ return 256;
+ case android.hardware.security.keymint.EcCurve.P_384:
+ return 384;
+ case android.hardware.security.keymint.EcCurve.P_521:
+ return 521;
+ default:
+ return -1;
+ }
+ }
+ }
+
+ /**
* Namespaces provide system developers and vendors with a way to use keystore without
* requiring an applications uid. Namespaces can be configured using SEPolicy.
* See <a href="https://source.android.com/security/keystore#access-control">
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
index 5216a908826b..ace2053cc1a7 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
@@ -203,6 +203,11 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
for (Authorization a : key.getAuthorizations()) {
if (a.keyParameter.tag == KeymasterDefs.KM_TAG_KEY_SIZE) {
keySizeBits = KeyStore2ParameterUtils.getUnsignedInt(a);
+ break;
+ } else if (a.keyParameter.tag == KeymasterDefs.KM_TAG_EC_CURVE) {
+ keySizeBits = KeyProperties.EcCurve.fromKeymasterCurve(
+ a.keyParameter.value.getEcCurve());
+ break;
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 9d424e904d59..f05cdc57fb70 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -66,6 +66,7 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.security.interfaces.ECKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -566,6 +567,22 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
spec.getMaxUsageCount()
));
}
+ if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(key.getAlgorithm())) {
+ if (key instanceof ECKey) {
+ ECKey ecKey = (ECKey) key;
+ importArgs.add(KeyStore2ParameterUtils.makeEnum(
+ KeymasterDefs.KM_TAG_EC_CURVE,
+ KeyProperties.EcCurve.toKeymasterCurve(ecKey.getParams())
+ ));
+ }
+ }
+ /* TODO: check for Ed25519(EdDSA) or X25519(XDH) key algorithm and
+ * add import args for KM_TAG_EC_CURVE as EcCurve.CURVE_25519.
+ * Currently conscrypt does not support EdDSA key import and XDH keys are not an
+ * instance of XECKey, hence these conditions are not added, once it is fully
+ * implemented by conscrypt, we can add CURVE_25519 argument for EdDSA and XDH
+ * algorithms.
+ */
} catch (IllegalArgumentException | IllegalStateException e) {
throw new KeyStoreException(e);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrDecorateView.java b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrDecorateView.java
index 51cf59c25502..ac9cdacec598 100644
--- a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrDecorateView.java
+++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrDecorateView.java
@@ -34,16 +34,16 @@ public class QrDecorateView extends View {
private static final float CORNER_LINE_LENGTH = 264f; // 264dp
private static final float CORNER_RADIUS = 16f; // 16dp
- final private int mCornerColor;
- final private int mFocusedCornerColor;
- final private int mBackgroundColor;
+ private final int mCornerColor;
+ private final int mFocusedCornerColor;
+ private final int mBackgroundColor;
- final private Paint mStrokePaint;
- final private Paint mTransparentPaint;
- final private Paint mBackgroundPaint;
+ private final Paint mStrokePaint;
+ private final Paint mTransparentPaint;
+ private final Paint mBackgroundPaint;
- final private float mRadius;
- final private float mInnerRidus;
+ private final float mRadius;
+ private final float mInnerRadius;
private Bitmap mMaskBitmap;
private Canvas mMaskCanvas;
@@ -72,7 +72,7 @@ public class QrDecorateView extends View {
mRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS,
getResources().getDisplayMetrics());
// Inner radius needs to minus stroke width for keeping the width of border consistent.
- mInnerRidus = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ mInnerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
CORNER_RADIUS - CORNER_STROKE_WIDTH, getResources().getDisplayMetrics());
mCornerColor = context.getResources().getColor(R.color.qr_corner_line_color);
@@ -95,7 +95,10 @@ public class QrDecorateView extends View {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- if(mMaskBitmap == null) {
+ if (!isLaidOut()) {
+ return;
+ }
+ if (mMaskBitmap == null) {
mMaskBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
mMaskCanvas = new Canvas(mMaskBitmap);
}
@@ -105,16 +108,18 @@ public class QrDecorateView extends View {
@Override
protected void onDraw(Canvas canvas) {
- // Set frame line color.
- mStrokePaint.setColor(mFocused ? mFocusedCornerColor : mCornerColor);
- // Draw background color.
- mMaskCanvas.drawColor(mBackgroundColor);
- // Draw outer corner.
- mMaskCanvas.drawRoundRect(mOuterFrame, mRadius, mRadius, mStrokePaint);
- // Draw inner transparent corner.
- mMaskCanvas.drawRoundRect(mInnerFrame, mInnerRidus, mInnerRidus, mTransparentPaint);
-
- canvas.drawBitmap(mMaskBitmap, 0, 0, mBackgroundPaint);
+ if (mMaskCanvas != null && mMaskBitmap != null) {
+ // Set frame line color.
+ mStrokePaint.setColor(mFocused ? mFocusedCornerColor : mCornerColor);
+ // Draw background color.
+ mMaskCanvas.drawColor(mBackgroundColor);
+ // Draw outer corner.
+ mMaskCanvas.drawRoundRect(mOuterFrame, mRadius, mRadius, mStrokePaint);
+ // Draw inner transparent corner.
+ mMaskCanvas.drawRoundRect(mInnerFrame, mInnerRadius, mInnerRadius, mTransparentPaint);
+
+ canvas.drawBitmap(mMaskBitmap, 0, 0, mBackgroundPaint);
+ }
super.onDraw(canvas);
}
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 3f1d1feec282..ae50b2358139 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -186,6 +186,10 @@ public class VpnManagerService extends IVpnManager.Stub {
synchronized (mVpns) {
for (int i = 0; i < mVpns.size(); i++) {
pw.println(mVpns.keyAt(i) + ": " + mVpns.valueAt(i).getPackage());
+ pw.increaseIndent();
+ mVpns.valueAt(i).dump(pw);
+ pw.decreaseIndent();
+ pw.println();
}
pw.decreaseIndent();
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c671a2c0cdad..0741d46b6f29 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -127,6 +127,8 @@ import android.system.keystore2.KeyDescriptor;
import android.system.keystore2.KeyPermission;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
+import android.util.LocalLog;
import android.util.Log;
import android.util.Range;
@@ -296,6 +298,10 @@ public class Vpn {
return mVpnProfileStore;
}
+ private static final int MAX_EVENTS_LOGS = 20;
+ private final LocalLog mUnderlyNetworkChanges = new LocalLog(MAX_EVENTS_LOGS);
+ private final LocalLog mVpnManagerEvents = new LocalLog(MAX_EVENTS_LOGS);
+
/**
* Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
* only applies to {@link VpnService} connections.
@@ -841,6 +847,9 @@ public class Vpn {
int errorCode, @NonNull final String packageName, @Nullable final String sessionKey,
@NonNull final VpnProfileState profileState, @Nullable final Network underlyingNetwork,
@Nullable final NetworkCapabilities nc, @Nullable final LinkProperties lp) {
+ mVpnManagerEvents.log("Event class=" + getVpnManagerEventClassName(errorClass)
+ + ", err=" + getVpnManagerEventErrorName(errorCode) + " for " + packageName
+ + " on session " + sessionKey);
final Intent intent = buildVpnManagerEventIntent(category, errorClass, errorCode,
packageName, sessionKey, profileState, underlyingNetwork, nc, lp);
return sendEventToVpnManagerApp(intent, packageName);
@@ -1572,6 +1581,7 @@ public class Vpn {
? Arrays.asList(mConfig.underlyingNetworks) : null);
mNetworkCapabilities = capsBuilder.build();
+ logUnderlyNetworkChanges(mNetworkCapabilities.getUnderlyingNetworks());
mNetworkAgent = mDeps.newNetworkAgent(mContext, mLooper, NETWORKTYPE /* logtag */,
mNetworkCapabilities, lp,
new NetworkScore.Builder().setLegacyInt(VPN_DEFAULT_SCORE).build(),
@@ -1599,6 +1609,11 @@ public class Vpn {
}
}
+ private void logUnderlyNetworkChanges(List<Network> networks) {
+ mUnderlyNetworkChanges.log("Switch to "
+ + ((networks != null) ? TextUtils.join(", ", networks) : "null"));
+ }
+
private void agentDisconnect(NetworkAgent networkAgent) {
if (networkAgent != null) {
networkAgent.unregister();
@@ -2928,7 +2943,6 @@ public class Vpn {
ikeConfiguration.isIkeExtensionEnabled(
IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE);
onIkeConnectionInfoChanged(token, ikeConfiguration.getIkeSessionConnectionInfo());
- mRetryCount = 0;
}
/**
@@ -3048,6 +3062,7 @@ public class Vpn {
}
doSendLinkProperties(networkAgent, lp);
+ mRetryCount = 0;
} catch (Exception e) {
Log.d(TAG, "Error in ChildOpened for token " + token, e);
onSessionLost(token, e);
@@ -3345,6 +3360,10 @@ public class Vpn {
}
private void scheduleRetryNewIkeSession() {
+ if (mScheduledHandleRetryIkeSessionFuture != null) {
+ Log.d(TAG, "There is a pending retrying task, skip the new retrying task");
+ return;
+ }
final long retryDelay = mDeps.getNextRetryDelaySeconds(mRetryCount++);
Log.d(TAG, "Retry new IKE session after " + retryDelay + " seconds.");
// If the default network is lost during the retry delay, the mActiveNetwork will be
@@ -4368,6 +4387,7 @@ public class Vpn {
// TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
// ConnectivityServiceTest.
if (SdkLevel.isAtLeastT()) {
+ mVpnManagerEvents.log(packageName + " stopped");
sendEventToVpnManagerApp(intent, packageName);
}
}
@@ -4535,8 +4555,10 @@ public class Vpn {
/** Proxy to allow different testing setups */
// TODO: b/240492694 Remove VpnNetworkAgentWrapper and this method when
// NetworkAgent#setUnderlyingNetworks can be un-finalized.
- private static void doSetUnderlyingNetworks(
+ private void doSetUnderlyingNetworks(
@NonNull NetworkAgent agent, @NonNull List<Network> networks) {
+ logUnderlyNetworkChanges(networks);
+
if (agent instanceof VpnNetworkAgentWrapper) {
((VpnNetworkAgentWrapper) agent).doSetUnderlyingNetworks(networks);
} else {
@@ -4655,4 +4677,57 @@ public class Vpn {
static Range<Integer> createUidRangeForUser(int userId) {
return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1);
}
+
+ private String getVpnManagerEventClassName(int code) {
+ switch (code) {
+ case VpnManager.ERROR_CLASS_NOT_RECOVERABLE:
+ return "ERROR_CLASS_NOT_RECOVERABLE";
+ case VpnManager.ERROR_CLASS_RECOVERABLE:
+ return "ERROR_CLASS_RECOVERABLE";
+ default:
+ return "UNKNOWN_CLASS";
+ }
+ }
+
+ private String getVpnManagerEventErrorName(int code) {
+ switch (code) {
+ case VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST:
+ return "ERROR_CODE_NETWORK_UNKNOWN_HOST";
+ case VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT:
+ return "ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT";
+ case VpnManager.ERROR_CODE_NETWORK_IO:
+ return "ERROR_CODE_NETWORK_IO";
+ case VpnManager.ERROR_CODE_NETWORK_LOST:
+ return "ERROR_CODE_NETWORK_LOST";
+ default:
+ return "UNKNOWN_ERROR";
+ }
+ }
+
+ /** Dumps VPN state. */
+ public void dump(IndentingPrintWriter pw) {
+ synchronized (Vpn.this) {
+ pw.println("Active package name: " + mPackage);
+ pw.println("Active vpn type: " + getActiveVpnType());
+ pw.println("NetworkCapabilities: " + mNetworkCapabilities);
+ if (isIkev2VpnRunner()) {
+ final IkeV2VpnRunner runner = ((IkeV2VpnRunner) mVpnRunner);
+ pw.println("Token: " + runner.mSessionKey);
+ pw.println("MOBIKE " + (runner.mMobikeEnabled ? "enabled" : "disabled"));
+ if (mDataStallSuspected) pw.println("Data stall suspected");
+ if (runner.mScheduledHandleDataStallFuture != null) {
+ pw.println("Reset session scheduled");
+ }
+ }
+ pw.println("mUnderlyNetworkChanges (most recent first):");
+ pw.increaseIndent();
+ mUnderlyNetworkChanges.reverseDump(pw);
+ pw.decreaseIndent();
+
+ pw.println("mVpnManagerEvent (most recent first):");
+ pw.increaseIndent();
+ mVpnManagerEvents.reverseDump(pw);
+ pw.decreaseIndent();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 5544669e1252..362b26ec762a 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -56,6 +56,7 @@ import android.content.pm.overlay.OverlayPaths;
import android.content.res.ApkAssets;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Environment;
import android.os.FabricatedOverlayInternal;
import android.os.HandlerThread;
@@ -876,7 +877,7 @@ public final class OverlayManagerService extends SystemService {
}
Slog.d(TAG, "commit failed: " + e.getMessage(), e);
throw new SecurityException("commit failed"
- + (DEBUG ? ": " + e.getMessage() : ""));
+ + (DEBUG || Build.IS_DEBUGGABLE ? ": " + e.getMessage() : ""));
}
} finally {
traceEnd(TRACE_TAG_RRO);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 46691a61930e..1e64701ebab7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3630,7 +3630,7 @@ class PackageManagerShellCommand extends ShellCommand {
fd = ParcelFileDescriptor.dup(getInFileDescriptor());
}
if (sizeBytes <= 0) {
- getErrPrintWriter().println("Error: must specify a APK size");
+ getErrPrintWriter().println("Error: must specify an APK size");
return 1;
}
diff --git a/services/core/java/com/android/server/pm/dex/OdsignStatsLogger.java b/services/core/java/com/android/server/pm/dex/OdsignStatsLogger.java
index fa08addc9b69..227a3a1d4317 100644
--- a/services/core/java/com/android/server/pm/dex/OdsignStatsLogger.java
+++ b/services/core/java/com/android/server/pm/dex/OdsignStatsLogger.java
@@ -39,6 +39,7 @@ public class OdsignStatsLogger {
// These need to be kept in sync with system/security/ondevice-signing/StatsReporter.{h, cpp}.
private static final String METRICS_FILE = "/data/misc/odsign/metrics/odsign-metrics.txt";
private static final String COMPOS_METRIC_NAME = "comp_os_artifacts_check_record";
+ private static final String ODSIGN_METRIC_NAME = "odsign_record";
/**
* Arrange for stats to be uploaded in the background.
@@ -64,18 +65,45 @@ public class OdsignStatsLogger {
for (String line : lines.split("\n")) {
String[] metrics = line.split(" ");
- if (metrics.length != 4 || !metrics[0].equals(COMPOS_METRIC_NAME)) {
- Slog.w(TAG, "Malformed metrics file");
- break;
+ if (line.isEmpty() || metrics.length < 1) {
+ Slog.w(TAG, "Empty metrics line");
+ continue;
}
- boolean currentArtifactsOk = metrics[1].equals("1");
- boolean compOsPendingArtifactsExists = metrics[2].equals("1");
- boolean useCompOsGeneratedArtifacts = metrics[3].equals("1");
+ switch (metrics[0]) {
+ case COMPOS_METRIC_NAME: {
+ if (metrics.length != 4) {
+ Slog.w(TAG, "Malformed CompOS metrics line '" + line + "'");
+ continue;
+ }
- ArtStatsLog.write(ArtStatsLog.EARLY_BOOT_COMP_OS_ARTIFACTS_CHECK_REPORTED,
- currentArtifactsOk, compOsPendingArtifactsExists,
- useCompOsGeneratedArtifacts);
+ boolean currentArtifactsOk = metrics[1].equals("1");
+ boolean compOsPendingArtifactsExists = metrics[2].equals("1");
+ boolean useCompOsGeneratedArtifacts = metrics[3].equals("1");
+
+ ArtStatsLog.write(ArtStatsLog.EARLY_BOOT_COMP_OS_ARTIFACTS_CHECK_REPORTED,
+ currentArtifactsOk, compOsPendingArtifactsExists,
+ useCompOsGeneratedArtifacts);
+ break;
+ }
+ case ODSIGN_METRIC_NAME: {
+ if (metrics.length != 2) {
+ Slog.w(TAG, "Malformed odsign metrics line '" + line + "'");
+ continue;
+ }
+
+ try {
+ int status = Integer.parseInt(metrics[1]);
+ ArtStatsLog.write(ArtStatsLog.ODSIGN_REPORTED, status);
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Malformed odsign metrics line '" + line + "'");
+ }
+
+ break;
+ }
+ default:
+ Slog.w(TAG, "Malformed metrics line '" + line + "'");
+ }
}
} catch (FileNotFoundException e) {
// This is normal and probably means no new metrics have been generated.
diff --git a/services/core/java/com/android/server/rollback/README.md b/services/core/java/com/android/server/rollback/README.md
index 0c5cc156f86d..08800dada564 100644
--- a/services/core/java/com/android/server/rollback/README.md
+++ b/services/core/java/com/android/server/rollback/README.md
@@ -1,4 +1,4 @@
-#Rollback Manager
+# Rollback Manager
## Introduction
@@ -7,9 +7,9 @@ updatability efforts. RollbackManager adds support for rolling back an APK or
APEX update to the previous version installed on the device, and reverting any
APK or APEX data to the state it was in at the time of install.
-##Rollback Basics
+## Rollback Basics
-###How Rollbacks Work
+### How Rollbacks Work
A new install parameter ENABLE_ROLLBACK can be specified to enable rollback when
updating an application. For example:
@@ -42,27 +42,27 @@ data taken when FooV2.apk was first installed.
See below for more details of shell commands for rollback.
-###Rollback Triggers
+### Rollback Triggers
-####Manually Triggered Rollback
+#### Manually Triggered Rollback
As mentioned above, it is possible to trigger rollback on device using a shell
command. This is for testing purposes only. We do not expect this mechanism to
be used in production in practice.
-####Watchdog Triggered Rollback
+#### Watchdog Triggered Rollback
Watchdog triggered rollback is intended to address severe issues with the
device. The platform provides several different watchdogs that can trigger
rollback.
-#####Package Watchdog
+##### Package Watchdog
There is a package watchdog service running on device that will trigger rollback
of an update if there are 5 ANRs or process crashes within a 1 minute window for
a package in the update.
-#####Native Watchdog
+##### Native Watchdog
If a native service crashes repeatedly after an update is installed, rollback
will be triggered. This particularly applies to updates that include APEXes
@@ -70,25 +70,25 @@ that may update native services, but note that as it is difficult to tell which
native services have been affected by an update, *any* crashing native service
will cause the rollback to be triggered.
-#####Explicit Health Check
+##### Explicit Health Check
There is an explicit check to verify the network stack is functional after an
update. If there is no network connectivity within a certain time period after
an update, rollback is triggered.
-####Server Triggered Rollback
+#### Server Triggered Rollback
The RollbackManager API may be used by the installer to roll back an update
based on a request from the server.
-##Rollback Details
+## Rollback Details
-###RollbackManager API
+### RollbackManager API
The RollbackManager API is an @SystemAPI guarded by the MANAGE_ROLLBACKS and
TEST_MANAGE_ROLLBACKS permissions. See RollbackManager.java for details about
the RollbackManager API.
-###Rollback of APEX modules
+### Rollback of APEX modules
Rollback is supported for APEX modules in addition to APK modules. In Q, there
was no concept of data associated with an APEX, so only the APEX itself is
@@ -100,7 +100,7 @@ terms of any state they persist on the system (outside of the APEX data
directories). For example, FooV2.apex must not change the file format of some
state stored on the device in such a way that FooV1.apex cannot read the file.
-###Rollback of MultiPackage Installs
+### Rollback of MultiPackage Installs
Rollback can be enabled for multi-package installs. This requires that all
packages in the install session, including the parent session, have the
@@ -119,7 +119,7 @@ If there is a problem enabling rollback for any package in the multi-package
install session, rollback will not be enabled for any package in the
multi-package install session.
-###Rollback of Staged Installs
+### Rollback of Staged Installs
Rollback can be enabled for staged installs, which require reboot to take
effect. If reboot was required when the package was updated, then reboot is
@@ -127,21 +127,21 @@ required when the package is rolled back. If no reboot was required when the
package was updated, then no reboot is required when the package is rolled back.
-###Rollbacks on Multi User Devices
+### Rollbacks on Multi User Devices
Rollbacks should work properly on devices with multiple users. There is special
handling of user data backup to ensure app user data is properly backed up and
restored for all users, even for credential encrypted users that have not been
unlocked at various points during the flow.
-###Rollback whitelist
+### Rollback whitelist
Outside of testing, rollback may only be enabled for packages listed in the
sysconfig rollback whitelist - see
`SystemConfig#getRollbackWhitelistedPackages`. Attempts to enable rollback for
non-whitelisted packages will fail.
-###Failure to Enable Rollback
+### Failure to Enable Rollback
There are a number of reasons why we may be unable to enable rollback for a
package, including:
@@ -158,13 +158,13 @@ If we are unable to enable rollback, the installation will proceed without
rollback enabled. Failing to enable rollback does not cause the installation to
fail.
-###Failure to Commit Rollback
+### Failure to Commit Rollback
For the most part, a rollback will remain available after failure to commit it.
This allows the caller to retry the rollback if they have reason to believe it
will not fail again the next time the commit of the rollback is attempted.
-###Installing Previously Rolled Back Packages
+### Installing Previously Rolled Back Packages
There is no logic in the platform itself to prevent installing a version of a
package that was previously rolled back.
@@ -175,7 +175,7 @@ package versions believed to be the main source of the bad update. The list of
installer to prevent reinstall of a previously rolled back package version if so
desired.
-###Rollback Expiration
+### Rollback Expiration
An available rollback is expired if the rollback lifetime has been exceeded or
if there is a new update to package associated with the rollback. When an
@@ -183,9 +183,9 @@ available rollback is expired, the backed up apk and userdata associated with
the rollback are deleted. Once a rollback is expired, it can no longer be
executed.
-##Shell Commands for Rollback
+## Shell Commands for Rollback
-###Installing an App with Rollback Enabled
+### Installing an App with Rollback Enabled
The `adb install` command accepts the `--enable-rollback` flag to install an app
with rollback enabled. For example:
@@ -194,7 +194,7 @@ with rollback enabled. For example:
$ adb install --enable-rollback FooV2.apk
```
-###Triggering Rollback Manually
+### Triggering Rollback Manually
If rollback is available for an application, the pm command can be used to
trigger rollback manually on device:
@@ -206,7 +206,7 @@ $ adb shell pm rollback-app com.example.foo
For rollback of staged installs, you have to manually reboot the device for the
rollback to take effect after running the 'pm rollback-app' command.
-###Listing the Status of Rollbacks on Device
+### Listing the Status of Rollbacks on Device
You can get a list with details about available and recently committed rollbacks
using dumpsys. For example:
@@ -246,9 +246,9 @@ committed.
The list of rollbacks is also included in bug reports. Search for "DUMP OF
SERVICE rollback".
-##Configuration Properties
+## Configuration Properties
-###Rollback Lifetime
+### Rollback Lifetime
Rollback lifetime refers to the maximum duration of time after the rollback is
first enabled that it will be available. The default is for rollbacks to be
@@ -263,7 +263,7 @@ $ adb shell device_config put rollback_boot rollback_lifetime_in_millis 17280000
The update will not take effect until after system server has been restarted.
-###Enable Rollback Timeout
+### Enable Rollback Timeout
The enable rollback timeout is how long RollbackManager is allowed to take to
enable rollback when performing an update. This includes the time needed to make
@@ -279,7 +279,7 @@ $ adb shell device_config put rollback enable_rollback_timeout 10000
The update will take effect for the next install with rollback enabled.
-##Limitations
+## Limitations
* You cannot enable rollback for the first version of an application installed
on the device. Only updates to a package previously installed on the device can
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 1ec191ed7c05..e14bbbd78ded 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -20,16 +20,15 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import android.app.ActivityManager.RunningTaskInfo;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.ArraySet;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
-import java.util.Comparator;
-import java.util.Iterator;
+import java.util.ArrayList;
import java.util.List;
-import java.util.TreeSet;
/**
* Class for resolving the set of running tasks in the system.
@@ -41,15 +40,13 @@ class RunningTasks {
static final int FLAG_CROSS_USERS = 1 << 2;
static final int FLAG_KEEP_INTENT_EXTRA = 1 << 3;
- // Comparator to sort by last active time (descending)
- private static final Comparator<Task> LAST_ACTIVE_TIME_COMPARATOR =
- (o1, o2) -> {
- return o1.lastActiveTime == o2.lastActiveTime
- ? Integer.signum(o2.mTaskId - o1.mTaskId) :
- Long.signum(o2.lastActiveTime - o1.lastActiveTime);
- };
-
- private final TreeSet<Task> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR);
+ // Tasks are sorted in order {focusedVisibleTasks, visibleTasks, invisibleTasks}.
+ private final ArrayList<Task> mTmpSortedTasks = new ArrayList<>();
+ // mTmpVisibleTasks, mTmpInvisibleTasks and mTmpFocusedTasks are sorted from top
+ // to bottom.
+ private final ArrayList<Task> mTmpVisibleTasks = new ArrayList<>();
+ private final ArrayList<Task> mTmpInvisibleTasks = new ArrayList<>();
+ private final ArrayList<Task> mTmpFocusedTasks = new ArrayList<>();
private int mCallingUid;
private int mUserId;
@@ -67,8 +64,6 @@ class RunningTasks {
return;
}
- // Gather all of the tasks across all of the tasks, and add them to the sorted set
- mTmpSortedSet.clear();
mCallingUid = callingUid;
mUserId = UserHandle.getUserId(callingUid);
mCrossUser = (flags & FLAG_CROSS_USERS) == FLAG_CROSS_USERS;
@@ -79,22 +74,67 @@ class RunningTasks {
mRecentTasks = root.mService.getRecentTasks();
mKeepIntentExtra = (flags & FLAG_KEEP_INTENT_EXTRA) == FLAG_KEEP_INTENT_EXTRA;
- final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
- PooledLambda.__(Task.class));
- root.forAllLeafTasks(c, false);
- c.recycle();
+ if (root instanceof RootWindowContainer) {
+ ((RootWindowContainer) root).forAllDisplays(dc -> {
+ final Task focusedTask = dc.mFocusedApp != null ? dc.mFocusedApp.getTask() : null;
+ if (focusedTask != null) {
+ mTmpFocusedTasks.add(focusedTask);
+ }
+ processTaskInWindowContainer(dc);
+ });
+ } else {
+ final DisplayContent dc = root.getDisplayContent();
+ final Task focusedTask = dc != null
+ ? (dc.mFocusedApp != null ? dc.mFocusedApp.getTask() : null)
+ : null;
+ // May not be include focusedTask if root is DisplayArea.
+ final boolean rootContainsFocusedTask = focusedTask != null
+ && focusedTask.isDescendantOf(root);
+ if (rootContainsFocusedTask) {
+ mTmpFocusedTasks.add(focusedTask);
+ }
+ processTaskInWindowContainer(root);
+ }
- // Take the first {@param maxNum} tasks and create running task infos for them
- final Iterator<Task> iter = mTmpSortedSet.iterator();
- while (iter.hasNext()) {
- if (maxNum == 0) {
- break;
+ final int visibleTaskCount = mTmpVisibleTasks.size();
+ for (int i = 0; i < mTmpFocusedTasks.size(); i++) {
+ final Task focusedTask = mTmpFocusedTasks.get(i);
+ final boolean containsFocusedTask = mTmpVisibleTasks.remove(focusedTask);
+ if (containsFocusedTask) {
+ // Put the visible focused task at the first position.
+ mTmpSortedTasks.add(focusedTask);
}
+ }
+ if (!mTmpVisibleTasks.isEmpty()) {
+ mTmpSortedTasks.addAll(mTmpVisibleTasks);
+ }
+ if (!mTmpInvisibleTasks.isEmpty()) {
+ mTmpSortedTasks.addAll(mTmpInvisibleTasks);
+ }
- final Task task = iter.next();
- list.add(createRunningTaskInfo(task));
- maxNum--;
+ // Take the first {@param maxNum} tasks and create running task infos for them
+ final int size = Math.min(maxNum, mTmpSortedTasks.size());
+ final long now = SystemClock.elapsedRealtime();
+ for (int i = 0; i < size; i++) {
+ final Task task = mTmpSortedTasks.get(i);
+ // Override the last active to current time for the visible tasks because the visible
+ // tasks can be considered to be currently active, the values are descending as
+ // the item order.
+ final long visibleActiveTime = i < visibleTaskCount ? now + size - i : -1;
+ list.add(createRunningTaskInfo(task, visibleActiveTime));
}
+
+ mTmpFocusedTasks.clear();
+ mTmpVisibleTasks.clear();
+ mTmpInvisibleTasks.clear();
+ mTmpSortedTasks.clear();
+ }
+
+ private void processTaskInWindowContainer(WindowContainer wc) {
+ final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
+ PooledLambda.__(Task.class));
+ wc.forAllLeafTasks(c, true);
+ c.recycle();
}
private void processTask(Task task) {
@@ -121,25 +161,20 @@ class RunningTasks {
// home & recent tasks
return;
}
-
if (task.isVisible()) {
- // For the visible task, update the last active time so that it can be used to determine
- // the order of the tasks (it may not be set for newly created tasks)
- task.touchActiveTime();
- if (!task.isFocused()) {
- // TreeSet doesn't allow the same value and make sure this task is lower than the
- // focused one.
- task.lastActiveTime -= mTmpSortedSet.size();
- }
+ mTmpVisibleTasks.add(task);
+ } else {
+ mTmpInvisibleTasks.add(task);
}
-
- mTmpSortedSet.add(task);
}
/** Constructs a {@link RunningTaskInfo} from a given {@param task}. */
- private RunningTaskInfo createRunningTaskInfo(Task task) {
+ private RunningTaskInfo createRunningTaskInfo(Task task, long visibleActiveTime) {
final RunningTaskInfo rti = new RunningTaskInfo();
task.fillTaskInfo(rti, !mKeepIntentExtra);
+ if (visibleActiveTime > 0) {
+ rti.lastActiveTime = visibleActiveTime;
+ }
// Fill in some deprecated values
rti.id = rti.taskId;
return rti;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index 33b236669ec7..13fc61cbf2fa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -61,55 +61,6 @@ public class RunningTasksTest extends WindowTestsBase {
}
@Test
- public void testCollectTasksByLastActiveTime() {
- // Create a number of stacks with tasks (of incrementing active time)
- final ArrayList<DisplayContent> displays = new ArrayList<>();
- final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build();
- displays.add(display);
-
- final int numStacks = 2;
- for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
- final Task stack = new TaskBuilder(mSupervisor)
- .setDisplay(display)
- .setOnTop(false)
- .build();
- }
-
- final int numTasks = 10;
- int activeTime = 0;
- final List<Task> rootTasks = new ArrayList<>();
- display.getDefaultTaskDisplayArea().forAllRootTasks(task -> {
- rootTasks.add(task);
- }, false /* traverseTopToBottom */);
- for (int i = 0; i < numTasks; i++) {
- final Task task =
- createTask(rootTasks.get(i % numStacks), ".Task" + i, i, activeTime++, null);
- doReturn(false).when(task).isVisible();
- }
-
- // Ensure that the latest tasks were returned in order of decreasing last active time,
- // collected from all tasks across all the stacks
- final int numFetchTasks = 5;
- ArrayList<RunningTaskInfo> tasks = new ArrayList<>();
- mRunningTasks.getTasks(5, tasks, FLAG_ALLOWED | FLAG_CROSS_USERS, mRootWindowContainer,
- -1 /* callingUid */, PROFILE_IDS);
- assertThat(tasks).hasSize(numFetchTasks);
- for (int i = 0; i < numFetchTasks; i++) {
- assertEquals(numTasks - i - 1, tasks.get(i).id);
- }
-
- // Ensure that requesting more than the total number of tasks only returns the subset
- // and does not crash
- tasks.clear();
- mRunningTasks.getTasks(100, tasks, FLAG_ALLOWED | FLAG_CROSS_USERS,
- mRootWindowContainer, -1 /* callingUid */, PROFILE_IDS);
- assertThat(tasks).hasSize(numTasks);
- for (int i = 0; i < numTasks; i++) {
- assertEquals(numTasks - i - 1, tasks.get(i).id);
- }
- }
-
- @Test
public void testTaskInfo_expectNoExtrasByDefault() {
final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build();
final int numTasks = 10;
@@ -120,7 +71,7 @@ public class RunningTasksTest extends WindowTestsBase {
.build();
final Bundle data = new Bundle();
data.putInt("key", 100);
- createTask(stack, ".Task" + i, i, i, data);
+ createTask(stack, ".Task" + i, i, data);
}
final int numFetchTasks = 5;
@@ -145,7 +96,7 @@ public class RunningTasksTest extends WindowTestsBase {
.build();
final Bundle data = new Bundle();
data.putInt("key", 100);
- createTask(stack, ".Task" + i, i, i, data);
+ createTask(stack, ".Task" + i, i, data);
}
final int numFetchTasks = 5;
@@ -162,46 +113,63 @@ public class RunningTasksTest extends WindowTestsBase {
}
@Test
- public void testUpdateLastActiveTimeOfVisibleTasks() {
+ public void testGetTasksSortByFocusAndVisibility() {
final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build();
+ final Task stack = new TaskBuilder(mSupervisor)
+ .setDisplay(display)
+ .setOnTop(true)
+ .build();
+
final int numTasks = 10;
final ArrayList<Task> tasks = new ArrayList<>();
for (int i = 0; i < numTasks; i++) {
- final Task task = createTask(null, ".Task" + i, i, i, null);
+ final Task task = createTask(stack, ".Task" + i, i, null);
doReturn(false).when(task).isVisible();
tasks.add(task);
}
- final Task visibleTask = tasks.get(0);
- doReturn(true).when(visibleTask).isVisible();
-
- final Task focusedTask = tasks.get(1);
+ final Task focusedTask = tasks.get(numTasks - 1);
doReturn(true).when(focusedTask).isVisible();
- doReturn(true).when(focusedTask).isFocused();
+ display.mFocusedApp = focusedTask.getTopNonFinishingActivity();
+
+ final Task visibleTaskTop = tasks.get(numTasks - 2);
+ doReturn(true).when(visibleTaskTop).isVisible();
- // Ensure that the last active time of visible tasks were updated while the focused one had
- // the largest last active time.
+ final Task visibleTaskBottom = tasks.get(numTasks - 3);
+ doReturn(true).when(visibleTaskBottom).isVisible();
+
+ // Ensure that the focused Task is on top, visible tasks below, then invisible tasks.
final int numFetchTasks = 5;
final ArrayList<RunningTaskInfo> fetchTasks = new ArrayList<>();
mRunningTasks.getTasks(numFetchTasks, fetchTasks,
FLAG_ALLOWED | FLAG_CROSS_USERS | FLAG_KEEP_INTENT_EXTRA, mRootWindowContainer,
-1 /* callingUid */, PROFILE_IDS);
assertThat(fetchTasks).hasSize(numFetchTasks);
- assertEquals(fetchTasks.get(0).id, focusedTask.mTaskId);
- assertEquals(fetchTasks.get(1).id, visibleTask.mTaskId);
+ for (int i = 0; i < numFetchTasks; i++) {
+ assertEquals(numTasks - i - 1, fetchTasks.get(i).id);
+ }
+
+ // Ensure that requesting more than the total number of tasks only returns the subset
+ // and does not crash
+ fetchTasks.clear();
+ mRunningTasks.getTasks(100, fetchTasks,
+ FLAG_ALLOWED | FLAG_CROSS_USERS | FLAG_KEEP_INTENT_EXTRA, mRootWindowContainer,
+ -1 /* callingUid */, PROFILE_IDS);
+ assertThat(fetchTasks).hasSize(numTasks);
+ for (int i = 0; i < numTasks; i++) {
+ assertEquals(numTasks - i - 1, fetchTasks.get(i).id);
+ }
}
/**
- * Create a task with a single activity in it, with the given last active time.
+ * Create a task with a single activity in it.
*/
- private Task createTask(Task stack, String className, int taskId,
- int lastActiveTime, Bundle extras) {
+ private Task createTask(Task stack, String className, int taskId, Bundle extras) {
final Task task = new TaskBuilder(mAtm.mTaskSupervisor)
.setComponent(new ComponentName(mContext.getPackageName(), className))
.setTaskId(taskId)
.setParentTaskFragment(stack)
.build();
- task.lastActiveTime = lastActiveTime;
final ActivityRecord activity = new ActivityBuilder(mAtm)
.setTask(task)
.setComponent(new ComponentName(mContext.getPackageName(), ".TaskActivity"))