diff options
95 files changed, 1139 insertions, 823 deletions
diff --git a/apct-tests/perftests/blobstore/Android.bp b/apct-tests/perftests/blobstore/Android.bp index 9064b4494ed1..2590fe3d843f 100644 --- a/apct-tests/perftests/blobstore/Android.bp +++ b/apct-tests/perftests/blobstore/Android.bp @@ -29,7 +29,7 @@ android_test { "androidx.test.rules", "androidx.annotation_annotation", "apct-perftests-utils", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", "collector-device-lib-platform", "androidx.benchmark_benchmark-macro", ], diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java index 0208dab33746..4e4780ff8948 100644 --- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java +++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java @@ -21,10 +21,10 @@ import android.app.UiAutomation; import android.os.ParcelFileDescriptor; import android.perftests.utils.TraceMarkParser; import android.perftests.utils.TraceMarkParser.TraceMarkSlice; -import android.support.test.uiautomator.UiDevice; import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.uiautomator.UiDevice; import java.io.BufferedReader; import java.io.IOException; diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java index 03e5468a342a..3cd9f50aee6a 100644 --- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java +++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java @@ -25,12 +25,12 @@ import android.perftests.utils.ManualBenchmarkState; import android.perftests.utils.PerfManualStatusReporter; import android.perftests.utils.TraceMarkParser; import android.perftests.utils.TraceMarkParser.TraceMarkSlice; -import android.support.test.uiautomator.UiDevice; import android.util.DataUnit; import androidx.benchmark.macro.MacrobenchmarkScope; import androidx.test.filters.LargeTest; import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.uiautomator.UiDevice; import com.android.utils.blob.FakeBlobData; diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp index e84aea1e7fac..b6ea54d3d53f 100644 --- a/apct-tests/perftests/packagemanager/Android.bp +++ b/apct-tests/perftests/packagemanager/Android.bp @@ -34,6 +34,55 @@ android_test { test_suites: ["device-tests"], data: [ + ":QueriesAll4", + ":QueriesAll31", + ":QueriesAll43", + ":QueriesAll15", + ":QueriesAll27", + ":QueriesAll39", + ":QueriesAll11", + ":QueriesAll23", + ":QueriesAll35", + ":QueriesAll47", + ":QueriesAll9", + ":QueriesAll19", + ":QueriesAll1", + ":QueriesAll5", + ":QueriesAll40", + ":QueriesAll20", + ":QueriesAll32", + ":QueriesAll48", + ":QueriesAll16", + ":QueriesAll28", + ":QueriesAll44", + ":QueriesAll12", + ":QueriesAll24", + ":QueriesAll36", + ":QueriesAll6", + ":QueriesAll2", + ":QueriesAll41", + ":QueriesAll21", + ":QueriesAll37", + ":QueriesAll49", + ":QueriesAll17", + ":QueriesAll29", + ":QueriesAll33", + ":QueriesAll45", + ":QueriesAll13", + ":QueriesAll25", + ":QueriesAll7", + ":QueriesAll3", + ":QueriesAll30", + ":QueriesAll42", + ":QueriesAll10", + ":QueriesAll26", + ":QueriesAll38", + ":QueriesAll18", + ":QueriesAll22", + ":QueriesAll34", + ":QueriesAll46", + ":QueriesAll14", + ":QueriesAll8", ":QueriesAll0", ":perfetto_artifacts", ], diff --git a/boot/OWNERS b/boot/OWNERS index 0e258d042c08..3fe1a41f10b2 100644 --- a/boot/OWNERS +++ b/boot/OWNERS @@ -2,5 +2,5 @@ file:platform/build/soong:/OWNERS # art-team@ manages the boot image profiles for frameworks -per-file boot-* = calin@google.com, yawanng@google.com, ngeoffray@google.com -per-file preloaded-classes* = calin@google.com, yawanng@google.com, ngeoffray@google.com +per-file boot-* = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com +per-file preloaded-classes* = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 6b6bc9728b7f..27dadda40407 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -107,6 +107,7 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const char CLOCK_ENABLED_PROP_NAME[] = "persist.sys.bootanim.clock.enabled"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; +static const int MAX_CHECK_EXIT_INTERVAL_US = 50000; static constexpr size_t TEXT_POS_LEN_MAX = 16; static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; @@ -1680,7 +1681,17 @@ bool BootAnimation::playAnimation(const Animation& animation) { checkExit(); } - usleep(part.pause * ns2us(frameDuration)); + int pauseDuration = part.pause * ns2us(frameDuration); + while(pauseDuration > 0 && !exitPending()){ + if (pauseDuration > MAX_CHECK_EXIT_INTERVAL_US) { + usleep(MAX_CHECK_EXIT_INTERVAL_US); + pauseDuration -= MAX_CHECK_EXIT_INTERVAL_US; + } else { + usleep(pauseDuration); + break; + } + checkExit(); + } if (exitPending() && !part.count && mCurrentInset >= mTargetInset && !part.hasFadingPhase()) { diff --git a/config/OWNERS b/config/OWNERS index 74813bc3e6da..6a5df76e96ab 100644 --- a/config/OWNERS +++ b/config/OWNERS @@ -1,8 +1,8 @@ include /ZYGOTE_OWNERS # art-team@ manages the boot image profiles -per-file boot-* = ngeoffray@google.com, vmarko@google.com -per-file dirty-image-objects = ngeoffray@google.com, vmarko@google.com -per-file generate-preloaded-classes.sh = ngeoffray@google.com, vmarko@google.com -per-file preloaded-classes* = ngeoffray@google.com, vmarko@google.com +per-file boot-* = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com +per-file dirty-image-objects = ishcheikin@google.com, ngeoffray@google.com, vmarko@google.com +per-file generate-preloaded-classes.sh = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com +per-file preloaded-classes* = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 2ea0d8235548..a320f1e9509c 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -11488,7 +11488,7 @@ public class Intent implements Parcelable, Cloneable { private void toUriInner(StringBuilder uri, String scheme, String defAction, String defPackage, int flags) { if (scheme != null) { - uri.append("scheme=").append(scheme).append(';'); + uri.append("scheme=").append(Uri.encode(scheme)).append(';'); } if (mAction != null && !mAction.equals(defAction)) { uri.append("action=").append(Uri.encode(mAction)).append(';'); diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java index b1252fd0b21f..49d3cac63124 100644 --- a/core/java/android/content/IntentSender.java +++ b/core/java/android/content/IntentSender.java @@ -19,6 +19,7 @@ package android.content; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager.PendingIntentInfo; +import android.app.ActivityOptions; import android.compat.annotation.UnsupportedAppUsage; import android.os.Bundle; import android.os.Handler; @@ -158,7 +159,7 @@ public class IntentSender implements Parcelable { */ public void sendIntent(Context context, int code, Intent intent, OnFinished onFinished, Handler handler) throws SendIntentException { - sendIntent(context, code, intent, onFinished, handler, null); + sendIntent(context, code, intent, onFinished, handler, null, null /* options */); } /** @@ -190,6 +191,42 @@ public class IntentSender implements Parcelable { public void sendIntent(Context context, int code, Intent intent, OnFinished onFinished, Handler handler, String requiredPermission) throws SendIntentException { + sendIntent(context, code, intent, onFinished, handler, requiredPermission, + null /* options */); + } + + /** + * Perform the operation associated with this IntentSender, allowing the + * caller to specify information about the Intent to use and be notified + * when the send has completed. + * + * @param context The Context of the caller. This may be null if + * <var>intent</var> is also null. + * @param code Result code to supply back to the IntentSender's target. + * @param intent Additional Intent data. See {@link Intent#fillIn + * Intent.fillIn()} for information on how this is applied to the + * original Intent. Use null to not modify the original Intent. + * @param onFinished The object to call back on when the send has + * completed, or null for no callback. + * @param handler Handler identifying the thread on which the callback + * should happen. If null, the callback will happen from the thread + * pool of the process. + * @param requiredPermission Name of permission that a recipient of the PendingIntent + * is required to hold. This is only valid for broadcast intents, and + * corresponds to the permission argument in + * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}. + * If null, no permission is required. + * @param options Additional options the caller would like to provide to modify the sending + * behavior. May be built from an {@link ActivityOptions} to apply to an activity start. + * + * @throws SendIntentException Throws CanceledIntentException if the IntentSender + * is no longer allowing more intents to be sent through it. + * @hide + */ + public void sendIntent(Context context, int code, Intent intent, + OnFinished onFinished, Handler handler, String requiredPermission, + @Nullable Bundle options) + throws SendIntentException { try { String resolvedType = intent != null ? intent.resolveTypeIfNeeded(context.getContentResolver()) @@ -199,7 +236,7 @@ public class IntentSender implements Parcelable { onFinished != null ? new FinishedDispatcher(this, onFinished, handler) : null, - requiredPermission, null); + requiredPermission, options); if (res < 0) { throw new SendIntentException(); } diff --git a/core/java/android/nfc/tech/NdefFormatable.java b/core/java/android/nfc/tech/NdefFormatable.java index f19d30258393..2240fe7f7d3b 100644 --- a/core/java/android/nfc/tech/NdefFormatable.java +++ b/core/java/android/nfc/tech/NdefFormatable.java @@ -124,6 +124,9 @@ public final class NdefFormatable extends BasicTagTechnology { try { int serviceHandle = mTag.getServiceHandle(); INfcTag tagService = mTag.getTagService(); + if (tagService == null) { + throw new IOException(); + } int errorCode = tagService.formatNdef(serviceHandle, MifareClassic.KEY_DEFAULT); switch (errorCode) { case ErrorCodes.SUCCESS: diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java index 5aa4e27fc2f3..7cdaecddbd70 100644 --- a/core/java/android/os/image/DynamicSystemClient.java +++ b/core/java/android/os/image/DynamicSystemClient.java @@ -202,6 +202,13 @@ public class DynamicSystemClient { public static final String ACTION_NOTIFY_IF_IN_USE = "android.os.image.action.NOTIFY_IF_IN_USE"; + /** + * Intent action: hide notifications about the status of {@code DynamicSystem}. + * @hide + */ + public static final String ACTION_HIDE_NOTIFICATION = + "android.os.image.action.HIDE_NOTIFICATION"; + /* * Intent Keys */ @@ -217,6 +224,28 @@ public class DynamicSystemClient { */ public static final String KEY_USERDATA_SIZE = "KEY_USERDATA_SIZE"; + /** + * Intent key: Whether to enable DynamicSystem immediately after installation is done. + * Note this will reboot the device automatically. + * @hide + */ + public static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED"; + + /** + * Intent key: Whether to leave DynamicSystem on device reboot. + * False indicates a sticky mode where device stays in DynamicSystem across reboots. + * @hide + */ + public static final String KEY_ONE_SHOT = "KEY_ONE_SHOT"; + + /** + * Intent key: Whether to use default strings when showing the dialog that prompts + * user for device credentials. + * False indicates using the custom strings provided by {@code DynamicSystem}. + * @hide + */ + public static final String KEY_KEYGUARD_USE_DEFAULT_STRINGS = + "KEY_KEYGUARD_USE_DEFAULT_STRINGS"; private static class IncomingHandler extends Handler { private final WeakReference<DynamicSystemClient> mWeakClient; diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS index d34b45bf1ff1..4603e43fd164 100644 --- a/core/java/android/permission/OWNERS +++ b/core/java/android/permission/OWNERS @@ -1,18 +1,19 @@ # Bug component: 137825 -evanseverson@google.com -evanxinchen@google.com ashfall@google.com -guojing@google.com +augale@google.com +evanseverson@google.com +fayey@google.com jaysullivan@google.com +joecastro@google.com kvakil@google.com mrulhania@google.com narayan@google.com ntmyren@google.com olekarg@google.com pyuli@google.com -raphk@google.com rmacgregor@google.com sergeynv@google.com theianchen@google.com +yutingfang@google.com zhanghai@google.com diff --git a/core/java/android/security/net/config/ManifestConfigSource.java b/core/java/android/security/net/config/ManifestConfigSource.java index b885e726918d..0e20997d307f 100644 --- a/core/java/android/security/net/config/ManifestConfigSource.java +++ b/core/java/android/security/net/config/ManifestConfigSource.java @@ -25,7 +25,7 @@ import java.util.Set; /** @hide */ public class ManifestConfigSource implements ConfigSource { - private static final boolean DBG = true; + private static final boolean DBG = false; private static final String LOG_TAG = "NetworkSecurityConfig"; private final Object mLock = new Object(); diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index d48d566fd860..e6dad27d595b 100755 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -24,12 +24,12 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.icu.text.DateFormatSymbols; import android.icu.text.DateTimePatternGenerator; +import android.icu.util.ULocale; import android.os.Build; import android.provider.Settings; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.SpannedString; -import android.text.TextUtils; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -265,11 +265,13 @@ public class DateFormat { * @return a string pattern suitable for use with {@link java.text.SimpleDateFormat}. */ public static String getBestDateTimePattern(Locale locale, String skeleton) { - DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(locale); + ULocale uLocale = ULocale.forLocale(locale); + DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(uLocale); boolean allowDuplicateFields = !CompatChanges.isChangeEnabled( DISALLOW_DUPLICATE_FIELD_IN_SKELETON); - return dtpg.getBestPattern(skeleton, DateTimePatternGenerator.MATCH_NO_OPTIONS, + String pattern = dtpg.getBestPattern(skeleton, DateTimePatternGenerator.MATCH_NO_OPTIONS, allowDuplicateFields); + return getCompatibleEnglishPattern(uLocale, pattern); } /** @@ -303,10 +305,11 @@ public class DateFormat { */ @UnsupportedAppUsage public static String getTimeFormatString(Context context, int userHandle) { - DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance( - context.getResources().getConfiguration().locale); - return is24HourFormat(context, userHandle) ? dtpg.getBestPattern("Hm") + ULocale uLocale = ULocale.forLocale(context.getResources().getConfiguration().locale); + DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(uLocale); + String pattern = is24HourFormat(context, userHandle) ? dtpg.getBestPattern("Hm") : dtpg.getBestPattern("hm"); + return getCompatibleEnglishPattern(uLocale, pattern); } /** @@ -713,4 +716,21 @@ public class DateFormat { public static DateFormatSymbols getIcuDateFormatSymbols(Locale locale) { return new DateFormatSymbols(android.icu.util.GregorianCalendar.class, locale); } + + /** + * See http://b/266731719. It mirrors the implementation in + * {@link libcore.icu.SimpleDateFormatData.DateTimeFormatStringGenerator#postProcessPattern} + */ + private static String getCompatibleEnglishPattern(ULocale locale, String pattern) { + if (pattern == null || locale == null || !"en".equals(locale.getLanguage())) { + return pattern; + } + + String region = locale.getCountry(); + if (region != null && !region.isEmpty() && !"US".equals(region)) { + return pattern; + } + + return pattern.replace('\u202f', ' '); + } } diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java index 3a74b2ed63a7..c7f745664561 100644 --- a/core/java/android/view/DisplayEventReceiver.java +++ b/core/java/android/view/DisplayEventReceiver.java @@ -138,8 +138,12 @@ public abstract class DisplayEventReceiver { mMessageQueue = null; } - static final class VsyncEventData { - + /** + * Class to capture all inputs required for syncing events data. + * + * @hide + */ + public static final class VsyncEventData { static final FrameTimeline[] INVALID_FRAME_TIMELINES = {new FrameTimeline(FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE)}; diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java index 3df09c24ca30..1f0e95ea305a 100644 --- a/core/java/android/widget/AnalogClock.java +++ b/core/java/android/widget/AnalogClock.java @@ -49,15 +49,18 @@ import java.util.Formatter; import java.util.Locale; /** - * This widget display an analogic clock with two hands for hours and - * minutes. + * This widget displays an analogic clock with two hands for hours and minutes. * * @attr ref android.R.styleable#AnalogClock_dial * @attr ref android.R.styleable#AnalogClock_hand_hour * @attr ref android.R.styleable#AnalogClock_hand_minute * @attr ref android.R.styleable#AnalogClock_hand_second * @attr ref android.R.styleable#AnalogClock_timeZone - * @deprecated This widget is no longer supported. + * @deprecated This widget is no longer supported; except for + * {@link android.widget.RemoteViews} use cases like + * <a href="https://developer.android.com/develop/ui/views/appwidgets/overview"> + * app widgets</a>. + * */ @RemoteView @Deprecated diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS index a1d571fc4350..52f18fb80c27 100644 --- a/core/java/com/android/internal/app/OWNERS +++ b/core/java/com/android/internal/app/OWNERS @@ -1,15 +1,16 @@ per-file *AppOp* = file:/core/java/android/permission/OWNERS per-file UnlaunchableAppActivity.java = file:/core/java/android/app/admin/WorkProfile_OWNERS per-file IntentForwarderActivity.java = file:/core/java/android/app/admin/WorkProfile_OWNERS -per-file *Resolver* = file:/packages/SystemUI/OWNERS -per-file *Chooser* = file:/packages/SystemUI/OWNERS -per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS -per-file AbstractMultiProfilePagerAdapter.java = file:/packages/SystemUI/OWNERS -per-file *EmptyStateProvider.java = file:/packages/SystemUI/OWNERS per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS per-file *SoundTrigger* = file:/media/java/android/media/soundtrigger/OWNERS +# Chooser and Resolver. +per-file *Chooser* = file:chooser/OWNERS +per-file *Resolver* = file:chooser/OWNERS +per-file SimpleIconFactory.java = file:chooser/OWNERS +per-file AbstractMultiProfilePagerAdapter.java = file:chooser/OWNERS +per-file *EmptyStateProvider.java = file:chooser/OWNERS # Voice Interaction per-file *Assist* = file:/core/java/android/service/voice/OWNERS diff --git a/core/java/com/android/internal/app/chooser/OWNERS b/core/java/com/android/internal/app/chooser/OWNERS index a6f1632e7b8c..0844cfa6d053 100644 --- a/core/java/com/android/internal/app/chooser/OWNERS +++ b/core/java/com/android/internal/app/chooser/OWNERS @@ -1 +1,3 @@ -file:/packages/SystemUI/OWNERS
\ No newline at end of file +# Bug component: 324112 + +include platform/packages/modules/IntentResolver:/OWNERS diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 05cad77ca9ab..d8aeb51c2e4d 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -1018,7 +1018,7 @@ public final class Zygote { * Applies debugger system properties to the zygote arguments. * * For eng builds all apps are debuggable. On userdebug and user builds - * if persist.debuggable.dalvik.vm.jdwp.enabled is 1 all apps are + * if persist.debug.dalvik.vm.jdwp.enabled is 1 all apps are * debuggable. Otherwise, the debugger state is specified via the * "--enable-jdwp" flag in the spawn request. * diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index cdb058028fdd..56c2a8647168 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -2382,36 +2382,31 @@ static jint android_media_AudioSystem_getSurroundFormats(JNIEnv *env, jobject th if (jSurroundFormats == nullptr) { ALOGE("jSurroundFormats is NULL"); - return (jint)AUDIO_JAVA_BAD_VALUE; + return static_cast<jint>(AUDIO_JAVA_BAD_VALUE); } if (!env->IsInstanceOf(jSurroundFormats, gMapClass)) { ALOGE("getSurroundFormats not a map"); - return (jint)AUDIO_JAVA_BAD_VALUE; + return static_cast<jint>(AUDIO_JAVA_BAD_VALUE); } jint jStatus; unsigned int numSurroundFormats = 0; - audio_format_t *surroundFormats = nullptr; - bool *surroundFormatsEnabled = nullptr; - status_t status = AudioSystem::getSurroundFormats(&numSurroundFormats, surroundFormats, - surroundFormatsEnabled); + status_t status = AudioSystem::getSurroundFormats(&numSurroundFormats, nullptr, nullptr); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status); - jStatus = nativeToJavaStatus(status); - goto exit; + return nativeToJavaStatus(status); } if (numSurroundFormats == 0) { - jStatus = (jint)AUDIO_JAVA_SUCCESS; - goto exit; + return static_cast<jint>(AUDIO_JAVA_SUCCESS); } - surroundFormats = (audio_format_t *)calloc(numSurroundFormats, sizeof(audio_format_t)); - surroundFormatsEnabled = (bool *)calloc(numSurroundFormats, sizeof(bool)); - status = AudioSystem::getSurroundFormats(&numSurroundFormats, surroundFormats, - surroundFormatsEnabled); + auto surroundFormats = std::make_unique<audio_format_t[]>(numSurroundFormats); + auto surroundFormatsEnabled = std::make_unique<bool[]>(numSurroundFormats); + status = AudioSystem::getSurroundFormats(&numSurroundFormats, &surroundFormats[0], + &surroundFormatsEnabled[0]); jStatus = nativeToJavaStatus(status); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status); - goto exit; + return jStatus; } for (size_t i = 0; i < numSurroundFormats; i++) { int audioFormat = audioFormatFromNative(surroundFormats[i]); @@ -2427,9 +2422,6 @@ static jint android_media_AudioSystem_getSurroundFormats(JNIEnv *env, jobject th env->DeleteLocalRef(enabled); } -exit: - free(surroundFormats); - free(surroundFormatsEnabled); return jStatus; } @@ -2439,31 +2431,28 @@ static jint android_media_AudioSystem_getReportedSurroundFormats(JNIEnv *env, jo if (jSurroundFormats == nullptr) { ALOGE("jSurroundFormats is NULL"); - return (jint)AUDIO_JAVA_BAD_VALUE; + return static_cast<jint>(AUDIO_JAVA_BAD_VALUE); } if (!env->IsInstanceOf(jSurroundFormats, gArrayListClass)) { ALOGE("jSurroundFormats not an arraylist"); - return (jint)AUDIO_JAVA_BAD_VALUE; + return static_cast<jint>(AUDIO_JAVA_BAD_VALUE); } jint jStatus; unsigned int numSurroundFormats = 0; - audio_format_t *surroundFormats = nullptr; - status_t status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, surroundFormats); + status_t status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, nullptr); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::getReportedSurroundFormats error %d", status); - jStatus = nativeToJavaStatus(status); - goto exit; + return nativeToJavaStatus(status); } if (numSurroundFormats == 0) { - jStatus = (jint)AUDIO_JAVA_SUCCESS; - goto exit; + return static_cast<jint>(AUDIO_JAVA_SUCCESS); } - surroundFormats = (audio_format_t *)calloc(numSurroundFormats, sizeof(audio_format_t)); - status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, surroundFormats); + auto surroundFormats = std::make_unique<audio_format_t[]>(numSurroundFormats); + status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, &surroundFormats[0]); jStatus = nativeToJavaStatus(status); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::getReportedSurroundFormats error %d", status); - goto exit; + return jStatus; } for (size_t i = 0; i < numSurroundFormats; i++) { int audioFormat = audioFormatFromNative(surroundFormats[i]); @@ -2477,8 +2466,6 @@ static jint android_media_AudioSystem_getReportedSurroundFormats(JNIEnv *env, jo env->DeleteLocalRef(surroundFormat); } -exit: - free(surroundFormats); return jStatus; } diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index 7205dd817eb5..c596c54d2780 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -1008,6 +1008,7 @@ message AppsExitInfoProto { optional int32 uid = 1; repeated .android.app.ApplicationExitInfoProto app_exit_info = 2; + repeated .android.app.ApplicationExitInfoProto app_recoverable_crash = 3; } repeated User users = 2; } diff --git a/core/tests/coretests/src/android/app/OWNERS b/core/tests/coretests/src/android/app/OWNERS index b3f399363aef..8d9461d8035d 100644 --- a/core/tests/coretests/src/android/app/OWNERS +++ b/core/tests/coretests/src/android/app/OWNERS @@ -4,3 +4,6 @@ per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS per-file *Notification* = file:/packages/SystemUI/OWNERS per-file *Zen* = file:/packages/SystemUI/OWNERS per-file *StatusBar* = file:/packages/SystemUI/OWNERS + +# A11Y and related +per-file *UiAutomation* = file:/services/accessibility/OWNERS diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java index 8459330cc07b..212cc44eefab 100644 --- a/core/tests/coretests/src/android/text/format/DateFormatTest.java +++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java @@ -156,8 +156,8 @@ public class DateFormatTest { @DisableCompatChanges({DateFormat.DISALLOW_DUPLICATE_FIELD_IN_SKELETON}) public void testGetBestDateTimePattern_enableDuplicateField() { // en-US uses 12-hour format by default. - assertEquals("h:mm\u202fa", DateFormat.getBestDateTimePattern(Locale.US, "jmma")); - assertEquals("h:mm\u202fa", DateFormat.getBestDateTimePattern(Locale.US, "ahmma")); + assertEquals("h:mm a", DateFormat.getBestDateTimePattern(Locale.US, "jmma")); + assertEquals("h:mm a", DateFormat.getBestDateTimePattern(Locale.US, "ahmma")); } private static void assertIllegalArgumentException(Locale l, String skeleton) { diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java index 39ed82ef40f3..381c0512c532 100644 --- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java +++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java @@ -139,16 +139,16 @@ public class DateUtilsTest { fixedTime, java.text.DateFormat.SHORT, java.text.DateFormat.FULL)); final long hourDuration = 2 * 60 * 60 * 1000; - assertEquals("5:30:15\u202fAM Greenwich Mean Time", DateUtils.formatSameDayTime( + assertEquals("5:30:15 AM Greenwich Mean Time", DateUtils.formatSameDayTime( fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.FULL)); - assertEquals("5:30:15\u202fAM", DateUtils.formatSameDayTime(fixedTime + hourDuration, + assertEquals("5:30:15 AM", DateUtils.formatSameDayTime(fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.DEFAULT)); - assertEquals("5:30:15\u202fAM GMT", DateUtils.formatSameDayTime(fixedTime + hourDuration, + assertEquals("5:30:15 AM GMT", DateUtils.formatSameDayTime(fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.LONG)); - assertEquals("5:30:15\u202fAM", DateUtils.formatSameDayTime(fixedTime + hourDuration, + assertEquals("5:30:15 AM", DateUtils.formatSameDayTime(fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.MEDIUM)); - assertEquals("5:30\u202fAM", DateUtils.formatSameDayTime(fixedTime + hourDuration, + assertEquals("5:30 AM", DateUtils.formatSameDayTime(fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.SHORT)); } diff --git a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java index d785c3c895b8..f26b50ed4e2a 100644 --- a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java +++ b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java @@ -21,10 +21,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.pm.FeatureInfo; import android.content.pm.PackageManager; -import android.os.RemoteException; import android.os.ServiceManager; -import android.security.GenerateRkpKey; -import android.security.keymaster.KeymasterDefs; class CredstoreIdentityCredentialStore extends IdentityCredentialStore { @@ -125,18 +122,7 @@ class CredstoreIdentityCredentialStore extends IdentityCredentialStore { @NonNull String docType) throws AlreadyPersonalizedException, DocTypeNotSupportedException { try { - IWritableCredential wc; - wc = mStore.createCredential(credentialName, docType); - try { - GenerateRkpKey keyGen = new GenerateRkpKey(mContext); - // We don't know what the security level is for the backing keymint, so go ahead and - // poke the provisioner for both TEE and SB. - keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT); - keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_STRONGBOX); - } catch (RemoteException e) { - // Not really an error state. Does not apply at all if RKP is unsupported or - // disabled on a given device. - } + IWritableCredential wc = mStore.createCredential(credentialName, docType); return new CredstoreWritableIdentityCredential(mContext, credentialName, docType, wc); } catch (android.os.RemoteException e) { throw new RuntimeException("Unexpected RemoteException ", e); diff --git a/keystore/java/android/security/GenerateRkpKey.java b/keystore/java/android/security/GenerateRkpKey.java deleted file mode 100644 index 698133287f63..000000000000 --- a/keystore/java/android/security/GenerateRkpKey.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security; - -import android.annotation.CheckResult; -import android.annotation.IntDef; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * GenerateKey is a helper class to handle interactions between Keystore and the RemoteProvisioner - * app. There are two cases where Keystore should use this class. - * - * (1) : An app generates a new attested key pair, so Keystore calls notifyKeyGenerated to let the - * RemoteProvisioner app check if the state of the attestation key pool is getting low enough - * to warrant provisioning more attestation certificates early. - * - * (2) : An app attempts to generate a new key pair, but the keystore service discovers it is out of - * attestation key pairs and cannot provide one for the given application. Keystore can then - * make a blocking call on notifyEmpty to allow the RemoteProvisioner app to get another - * attestation certificate chain provisioned. - * - * In most cases, the proper usage of (1) should preclude the need for (2). - * - * @hide - */ -public class GenerateRkpKey { - private static final String TAG = "GenerateRkpKey"; - - private static final int NOTIFY_EMPTY = 0; - private static final int NOTIFY_KEY_GENERATED = 1; - private static final int TIMEOUT_MS = 1000; - - private IGenerateRkpKeyService mBinder; - private Context mContext; - private CountDownLatch mCountDownLatch; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, value = { - IGenerateRkpKeyService.Status.OK, - IGenerateRkpKeyService.Status.NO_NETWORK_CONNECTIVITY, - IGenerateRkpKeyService.Status.NETWORK_COMMUNICATION_ERROR, - IGenerateRkpKeyService.Status.DEVICE_NOT_REGISTERED, - IGenerateRkpKeyService.Status.HTTP_CLIENT_ERROR, - IGenerateRkpKeyService.Status.HTTP_SERVER_ERROR, - IGenerateRkpKeyService.Status.HTTP_UNKNOWN_ERROR, - IGenerateRkpKeyService.Status.INTERNAL_ERROR, - }) - public @interface Status { - } - - private ServiceConnection mConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName className, IBinder service) { - mBinder = IGenerateRkpKeyService.Stub.asInterface(service); - mCountDownLatch.countDown(); - } - - @Override public void onBindingDied(ComponentName className) { - mCountDownLatch.countDown(); - } - - @Override - public void onServiceDisconnected(ComponentName className) { - mBinder = null; - } - }; - - /** - * Constructor which takes a Context object. - */ - public GenerateRkpKey(Context context) { - mContext = context; - } - - @Status - private int bindAndSendCommand(int command, int securityLevel) throws RemoteException { - Intent intent = new Intent(IGenerateRkpKeyService.class.getName()); - ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); - int returnCode = IGenerateRkpKeyService.Status.OK; - if (comp == null) { - // On a system that does not use RKP, the RemoteProvisioner app won't be installed. - return returnCode; - } - intent.setComponent(comp); - mCountDownLatch = new CountDownLatch(1); - Executor executor = Executors.newCachedThreadPool(); - if (!mContext.bindService(intent, Context.BIND_AUTO_CREATE, executor, mConnection)) { - throw new RemoteException("Failed to bind to GenerateRkpKeyService"); - } - try { - mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Log.e(TAG, "Interrupted: ", e); - } - if (mBinder != null) { - switch (command) { - case NOTIFY_EMPTY: - returnCode = mBinder.generateKey(securityLevel); - break; - case NOTIFY_KEY_GENERATED: - mBinder.notifyKeyGenerated(securityLevel); - break; - default: - Log.e(TAG, "Invalid case for command"); - } - } else { - Log.e(TAG, "Binder object is null; failed to bind to GenerateRkpKeyService."); - returnCode = IGenerateRkpKeyService.Status.INTERNAL_ERROR; - } - mContext.unbindService(mConnection); - return returnCode; - } - - /** - * Fulfills the use case of (2) described in the class documentation. Blocks until the - * RemoteProvisioner application can get new attestation keys signed by the server. - * @return the status of the key generation - */ - @CheckResult - @Status - public int notifyEmpty(int securityLevel) throws RemoteException { - return bindAndSendCommand(NOTIFY_EMPTY, securityLevel); - } - - /** - * Fulfills the use case of (1) described in the class documentation. Non blocking call. - */ - public void notifyKeyGenerated(int securityLevel) throws RemoteException { - bindAndSendCommand(NOTIFY_KEY_GENERATED, securityLevel); - } -} diff --git a/keystore/java/android/security/GenerateRkpKeyException.java b/keystore/java/android/security/GenerateRkpKeyException.java deleted file mode 100644 index a2d65e4e7119..000000000000 --- a/keystore/java/android/security/GenerateRkpKeyException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security; - -/** - * Thrown on problems in attempting to attest to a key using a remotely provisioned key. - * - * @hide - */ -public class GenerateRkpKeyException extends Exception { - - /** - * Constructs a new {@code GenerateRkpKeyException}. - */ - public GenerateRkpKeyException() { - } -} diff --git a/keystore/java/android/security/IGenerateRkpKeyService.aidl b/keystore/java/android/security/IGenerateRkpKeyService.aidl deleted file mode 100644 index eeaeb27a7c77..000000000000 --- a/keystore/java/android/security/IGenerateRkpKeyService.aidl +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security; - -/** - * Interface to allow the framework to notify the RemoteProvisioner app when keys are empty. This - * will be used if Keystore replies with an error code NO_KEYS_AVAILABLE in response to an - * attestation request. The framework can then synchronously call generateKey() to get more - * attestation keys generated and signed. Upon return, the caller can be certain an attestation key - * is available. - * - * @hide - */ -interface IGenerateRkpKeyService { - @JavaDerive(toString=true) - @Backing(type="int") - enum Status { - /** No error(s) occurred */ - OK = 0, - /** Unable to provision keys due to a lack of internet connectivity. */ - NO_NETWORK_CONNECTIVITY = 1, - /** An error occurred while communicating with the RKP server. */ - NETWORK_COMMUNICATION_ERROR = 2, - /** The given device was not registered with the RKP backend. */ - DEVICE_NOT_REGISTERED = 4, - /** The RKP server returned an HTTP client error, indicating a misbehaving client. */ - HTTP_CLIENT_ERROR = 5, - /** The RKP server returned an HTTP server error, indicating something went wrong on the server. */ - HTTP_SERVER_ERROR = 6, - /** The RKP server returned an HTTP status that is unknown. This should never happen. */ - HTTP_UNKNOWN_ERROR = 7, - /** An unexpected internal error occurred. This should never happen. */ - INTERNAL_ERROR = 8, - } - - /** - * Ping the provisioner service to let it know an app generated a key. This may or may not have - * consumed a remotely provisioned attestation key, so the RemoteProvisioner app should check. - */ - oneway void notifyKeyGenerated(in int securityLevel); - - /** - * Ping the provisioner service to indicate there are no remaining attestation keys left. - */ - Status generateKey(in int securityLevel); -} diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index c3b0f9bc16d3..474b7ea56be9 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -20,7 +20,6 @@ import static android.security.keystore2.AndroidKeyStoreCipherSpiBase.DEFAULT_MG import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityThread; import android.content.Context; import android.hardware.security.keymint.EcCurve; import android.hardware.security.keymint.KeyParameter; @@ -28,9 +27,6 @@ import android.hardware.security.keymint.KeyPurpose; import android.hardware.security.keymint.SecurityLevel; import android.hardware.security.keymint.Tag; import android.os.Build; -import android.os.RemoteException; -import android.security.GenerateRkpKey; -import android.security.IGenerateRkpKeyService; import android.security.KeyPairGeneratorSpec; import android.security.KeyStore2; import android.security.KeyStoreException; @@ -621,45 +617,6 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato @Override public KeyPair generateKeyPair() { - GenerateKeyPairHelperResult result = new GenerateKeyPairHelperResult(0, null); - for (int i = 0; i < 2; i++) { - /** - * NOTE: There is no need to delay between re-tries because the call to - * GenerateRkpKey.notifyEmpty() will delay for a while before returning. - */ - result = generateKeyPairHelper(); - if (result.rkpStatus == KeyStoreException.RKP_SUCCESS && result.keyPair != null) { - return result.keyPair; - } - } - - // RKP failure - if (result.rkpStatus != KeyStoreException.RKP_SUCCESS) { - KeyStoreException ksException = new KeyStoreException(ResponseCode.OUT_OF_KEYS, - "Could not get RKP keys", result.rkpStatus); - throw new ProviderException("Failed to provision new attestation keys.", ksException); - } - - return result.keyPair; - } - - private static class GenerateKeyPairHelperResult { - // Zero indicates success, non-zero indicates failure. Values should be - // {@link android.security.KeyStoreException#RKP_TEMPORARILY_UNAVAILABLE}, - // {@link android.security.KeyStoreException#RKP_SERVER_REFUSED_ISSUANCE}, - // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_CONNECTIVITY} - // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_SOFTWARE_REBOOT} - public final int rkpStatus; - @Nullable - public final KeyPair keyPair; - - private GenerateKeyPairHelperResult(int rkpStatus, KeyPair keyPair) { - this.rkpStatus = rkpStatus; - this.keyPair = keyPair; - } - } - - private GenerateKeyPairHelperResult generateKeyPairHelper() { if (mKeyStore == null || mSpec == null) { throw new IllegalStateException("Not initialized"); } @@ -697,26 +654,12 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato AndroidKeyStorePublicKey publicKey = AndroidKeyStoreProvider.makeAndroidKeyStorePublicKeyFromKeyEntryResponse( descriptor, metadata, iSecurityLevel, mKeymasterAlgorithm); - GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread - .currentApplication()); - try { - if (mSpec.getAttestationChallenge() != null) { - keyGen.notifyKeyGenerated(securityLevel); - } - } catch (RemoteException e) { - // This is not really an error state, and necessarily does not apply to non RKP - // systems or hybrid systems where RKP is not currently turned on. - Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.", e); - } success = true; - KeyPair kp = new KeyPair(publicKey, publicKey.getPrivateKey()); - return new GenerateKeyPairHelperResult(0, kp); + return new KeyPair(publicKey, publicKey.getPrivateKey()); } catch (KeyStoreException e) { switch (e.getErrorCode()) { case KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE: throw new StrongBoxUnavailableException("Failed to generated key pair.", e); - case ResponseCode.OUT_OF_KEYS: - return checkIfRetryableOrThrow(e, securityLevel); default: ProviderException p = new ProviderException("Failed to generate key pair.", e); if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) { @@ -742,55 +685,6 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato } } - // In case keystore reports OUT_OF_KEYS, call this handler in an attempt to remotely provision - // some keys. - GenerateKeyPairHelperResult checkIfRetryableOrThrow(KeyStoreException e, int securityLevel) { - GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread - .currentApplication()); - KeyStoreException ksException; - try { - final int keyGenStatus = keyGen.notifyEmpty(securityLevel); - // Default stance: temporary error. This is a hint to the caller to try again with - // exponential back-off. - int rkpStatus; - switch (keyGenStatus) { - case IGenerateRkpKeyService.Status.NO_NETWORK_CONNECTIVITY: - rkpStatus = KeyStoreException.RKP_FETCHING_PENDING_CONNECTIVITY; - break; - case IGenerateRkpKeyService.Status.DEVICE_NOT_REGISTERED: - rkpStatus = KeyStoreException.RKP_SERVER_REFUSED_ISSUANCE; - break; - case IGenerateRkpKeyService.Status.OK: - // Explicitly return not-OK here so we retry in generateKeyPair. All other cases - // should throw because a retry doesn't make sense if we didn't actually - // provision fresh keys. - return new GenerateKeyPairHelperResult( - KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE, null); - case IGenerateRkpKeyService.Status.NETWORK_COMMUNICATION_ERROR: - case IGenerateRkpKeyService.Status.HTTP_CLIENT_ERROR: - case IGenerateRkpKeyService.Status.HTTP_SERVER_ERROR: - case IGenerateRkpKeyService.Status.HTTP_UNKNOWN_ERROR: - case IGenerateRkpKeyService.Status.INTERNAL_ERROR: - default: - // These errors really should never happen. The best we can do is assume they - // are transient and hint to the caller to retry with back-off. - rkpStatus = KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE; - break; - } - ksException = new KeyStoreException( - ResponseCode.OUT_OF_KEYS, - "Out of RKP keys due to IGenerateRkpKeyService status: " + keyGenStatus, - rkpStatus); - } catch (RemoteException f) { - ksException = new KeyStoreException( - ResponseCode.OUT_OF_KEYS, - "Remote exception: " + f.getMessage(), - KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE); - } - ksException.initCause(e); - throw new ProviderException("Failed to provision new attestation keys.", ksException); - } - private void addAttestationParameters(@NonNull List<KeyParameter> params) throws ProviderException, IllegalArgumentException, DeviceIdAttestationException { byte[] challenge = mSpec.getAttestationChallenge(); diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS index 852edef544b8..f0ed6ee5cb67 100644 --- a/libs/WindowManager/Shell/OWNERS +++ b/libs/WindowManager/Shell/OWNERS @@ -1,4 +1,4 @@ xutan@google.com # Give submodule owners in shell resource approval -per-file res*/*/*.xml = hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com +per-file res*/*/*.xml = atsjenk@google.com, hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS index 926cfb3b12ef..deb7c6db338f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS @@ -1,2 +1,3 @@ # WM shell sub-module desktop owners +atsjenk@google.com madym@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS index 0c2d5c49f830..ccbb9cf298a2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS @@ -1,2 +1,3 @@ # WM shell sub-module freeform owners +atsjenk@google.com madym@google.com diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS index 1c28c3d58ccb..64dfc3ef845d 100644 --- a/libs/WindowManager/Shell/tests/OWNERS +++ b/libs/WindowManager/Shell/tests/OWNERS @@ -7,3 +7,4 @@ lbill@google.com madym@google.com hwwang@google.com chenghsiuchang@google.com +atsjenk@google.com diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 60f77359bded..8f022accaccb 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -55,6 +55,10 @@ cc_defaults { // GCC false-positives on this warning, and since we -Werror that's // a problem "-Wno-free-nonheap-object", + + // Do not de-optimise cold code paths in AFDO. + // Some code paths might be infrequently executed but critical to latency. + "-fno-profile-sample-accurate", ], include_dirs: [ diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp index 8e350d5012a5..63c36f85be20 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp @@ -53,6 +53,8 @@ SkiaOpenGLPipeline::~SkiaOpenGLPipeline() { } MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() { + bool wasSurfaceless = mEglManager.isCurrent(EGL_NO_SURFACE); + // In case the surface was destroyed (e.g. a previous trimMemory call) we // need to recreate it here. if (!isSurfaceReady() && mNativeWindow) { @@ -63,6 +65,37 @@ MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() { if (!mEglManager.makeCurrent(mEglSurface, &error)) { return MakeCurrentResult::AlreadyCurrent; } + + // Make sure read/draw buffer state of default framebuffer is GL_BACK. Vendor implementations + // disagree on the draw/read buffer state if the default framebuffer transitions from a surface + // to EGL_NO_SURFACE and vice-versa. There was a related discussion within Khronos on this topic. + // See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13534. + // The discussion was not resolved with a clear consensus + if (error == 0 && wasSurfaceless && mEglSurface != EGL_NO_SURFACE) { + GLint curReadFB = 0; + GLint curDrawFB = 0; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &curReadFB); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curDrawFB); + + GLint buffer = GL_NONE; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glGetIntegerv(GL_DRAW_BUFFER0, &buffer); + if (buffer == GL_NONE) { + const GLenum drawBuffer = GL_BACK; + glDrawBuffers(1, &drawBuffer); + } + + glGetIntegerv(GL_READ_BUFFER, &buffer); + if (buffer == GL_NONE) { + glReadBuffer(GL_BACK); + } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, curReadFB); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, curDrawFB); + + GL_CHECKPOINT(LOW); + } + return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded; } diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING index 23ee5055f5cc..6e1fec2610d2 100644 --- a/media/TEST_MAPPING +++ b/media/TEST_MAPPING @@ -12,16 +12,16 @@ ] }, { - "name": "GtsMediaTestCases", + "name": "WvtsDeviceTestCases", "options" : [ { "include-annotation": "android.platform.test.annotations.Presubmit" }, { - "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests" + "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests" }, { - "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests" + "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests" } ], "file_patterns": ["(?i)drm|crypto"] diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 5b0c2a203022..b878bcf5dfef 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -43,6 +43,8 @@ #include <android_runtime/android_hardware_HardwareBuffer.h> +#include <android-base/stringprintf.h> + #include <binder/MemoryDealer.h> #include <cutils/compiler.h> @@ -1099,7 +1101,8 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) { ALOGE("Could not create MediaCodec.BufferInfo."); env->ExceptionClear(); } - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "Fatal error: could not create MediaCodec.BufferInfo object"); return; } @@ -1121,7 +1124,8 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) { ALOGE("Could not create CodecException object."); env->ExceptionClear(); } - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "Fatal error: could not create CodecException object"); return; } @@ -1134,7 +1138,9 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) { CHECK(msg->findMessage("format", &format)); if (OK != ConvertMessageToMap(env, format, &obj)) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "Fatal error: failed to convert format " + "from native to Java object"); return; } @@ -1166,7 +1172,8 @@ void JMediaCodec::handleFirstTunnelFrameReadyNotification(const sp<AMessage> &ms status_t err = ConvertMessageToMap(env, data, &obj); if (err != OK) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "Fatal error: failed to convert format from native to Java object"); return; } @@ -1187,7 +1194,8 @@ void JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) { status_t err = ConvertMessageToMap(env, data, &obj); if (err != OK) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + "Fatal error: failed to convert format from native to Java object"); return; } @@ -1198,6 +1206,18 @@ void JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) { env->DeleteLocalRef(obj); } +std::string JMediaCodec::getExceptionMessage(const char *msg = nullptr) const { + if (mCodec == nullptr) { + return msg ?: ""; + } + std::string prefix = ""; + if (msg && msg[0] != '\0') { + prefix.append(msg); + prefix.append("\n"); + } + return prefix + mCodec->getErrorLog().extract(); +} + void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatCallbackNotify: @@ -1347,9 +1367,17 @@ static void throwCryptoException(JNIEnv *env, status_t err, const char *msg, env->Throw(exception); } +static std::string GetExceptionMessage(const sp<JMediaCodec> &codec, const char *msg) { + if (codec == NULL) { + return msg ?: "codec is released already"; + } + return codec->getExceptionMessage(msg); +} + static jint throwExceptionAsNecessary( JNIEnv *env, status_t err, int32_t actionCode = ACTION_CODE_FATAL, - const char *msg = NULL, const sp<ICrypto>& crypto = NULL) { + const char *msg = NULL, const sp<ICrypto>& crypto = NULL, + const sp<JMediaCodec> &codec = NULL) { switch (err) { case OK: return 0; @@ -1364,23 +1392,38 @@ static jint throwExceptionAsNecessary( return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED; case INVALID_OPERATION: - jniThrowException(env, "java/lang/IllegalStateException", msg); + jniThrowException( + env, "java/lang/IllegalStateException", + GetExceptionMessage(codec, msg).c_str()); return 0; case BAD_VALUE: - jniThrowException(env, "java/lang/IllegalArgumentException", msg); + jniThrowException( + env, "java/lang/IllegalArgumentException", + GetExceptionMessage(codec, msg).c_str()); return 0; default: if (isCryptoError(err)) { - throwCryptoException(env, err, msg, crypto); + throwCryptoException( + env, err, + GetExceptionMessage(codec, msg).c_str(), + crypto); return 0; } - throwCodecException(env, err, actionCode, msg); + throwCodecException( + env, err, actionCode, + GetExceptionMessage(codec, msg).c_str()); return 0; } } +static jint throwExceptionAsNecessary( + JNIEnv *env, status_t err, const sp<JMediaCodec> &codec, + int32_t actionCode = ACTION_CODE_FATAL) { + return throwExceptionAsNecessary(env, err, actionCode, NULL, NULL, codec); +} + static void android_media_MediaCodec_native_enableOnFirstTunnelFrameReadyListener( JNIEnv *env, jobject thiz, @@ -1388,13 +1431,13 @@ static void android_media_MediaCodec_native_enableOnFirstTunnelFrameReadyListene sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t err = codec->enableOnFirstTunnelFrameReadyListener(enabled); - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_native_enableOnFrameRenderedListener( @@ -1404,13 +1447,13 @@ static void android_media_MediaCodec_native_enableOnFrameRenderedListener( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t err = codec->enableOnFrameRenderedListener(enabled); - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_native_setCallback( @@ -1420,13 +1463,13 @@ static void android_media_MediaCodec_native_setCallback( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t err = codec->setCallback(cb); - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_native_configure( @@ -1440,7 +1483,7 @@ static void android_media_MediaCodec_native_configure( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } @@ -1478,7 +1521,7 @@ static void android_media_MediaCodec_native_configure( err = codec->configure(format, bufferProducer, crypto, descrambler, flags); - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_native_setSurface( @@ -1488,7 +1531,7 @@ static void android_media_MediaCodec_native_setSurface( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } @@ -1507,7 +1550,7 @@ static void android_media_MediaCodec_native_setSurface( } status_t err = codec->setSurface(bufferProducer); - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } sp<PersistentSurface> android_media_MediaCodec_getPersistentInputSurface( @@ -1611,7 +1654,7 @@ static void android_media_MediaCodec_setInputSurface( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } @@ -1625,7 +1668,7 @@ static void android_media_MediaCodec_setInputSurface( } status_t err = codec->setInputSurface(persistentSurface); if (err != NO_ERROR) { - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } } @@ -1635,7 +1678,7 @@ static jobject android_media_MediaCodec_createInputSurface(JNIEnv* env, sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } @@ -1643,7 +1686,7 @@ static jobject android_media_MediaCodec_createInputSurface(JNIEnv* env, sp<IGraphicBufferProducer> bufferProducer; status_t err = codec->createInputSurface(&bufferProducer); if (err != NO_ERROR) { - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); return NULL; } @@ -1658,13 +1701,13 @@ static void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) { sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t err = codec->start(); - throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, "start failed"); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) { @@ -1673,13 +1716,13 @@ static void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) { sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t err = codec->stop(); - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) { @@ -1688,7 +1731,7 @@ static void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) { sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } @@ -1701,7 +1744,7 @@ static void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) { // trigger an IllegalStateException. err = UNKNOWN_ERROR; } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) { @@ -1710,13 +1753,13 @@ static void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) { sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t err = codec->flush(); - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_queueInputBuffer( @@ -1732,7 +1775,7 @@ static void android_media_MediaCodec_queueInputBuffer( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } @@ -1742,7 +1785,8 @@ static void android_media_MediaCodec_queueInputBuffer( index, offset, size, timestampUs, flags, &errorDetailMsg); throwExceptionAsNecessary( - env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str()); + env, err, ACTION_CODE_FATAL, + codec->getExceptionMessage(errorDetailMsg.c_str()).c_str()); } struct NativeCryptoInfo { @@ -1766,7 +1810,9 @@ struct NativeCryptoInfo { } else if (jmode == gCryptoModes.AesCbc) { mMode = CryptoPlugin::kMode_AES_CBC; } else { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary( + env, INVALID_OPERATION, ACTION_CODE_FATAL, + base::StringPrintf("unrecognized crypto mode: %d", jmode).c_str()); return; } @@ -1902,7 +1948,7 @@ static void android_media_MediaCodec_queueSecureInputBuffer( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } @@ -1932,7 +1978,9 @@ static void android_media_MediaCodec_queueSecureInputBuffer( } else if (jmode == gCryptoModes.AesCbc) { mode = CryptoPlugin::kMode_AES_CBC; } else { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary( + env, INVALID_OPERATION, ACTION_CODE_FATAL, + base::StringPrintf("Unrecognized crypto mode: %d", jmode).c_str()); return; } @@ -2051,8 +2099,8 @@ static void android_media_MediaCodec_queueSecureInputBuffer( subSamples = NULL; throwExceptionAsNecessary( - env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str(), - codec->getCrypto()); + env, err, ACTION_CODE_FATAL, + codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto()); } static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jclass, jobject bufferObj) { @@ -2394,14 +2442,16 @@ static void android_media_MediaCodec_native_queueLinearBlock( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == nullptr || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } sp<AMessage> tunings; status_t err = ConvertKeyValueListsToAMessage(env, keys, values, &tunings); if (err != OK) { - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary( + env, err, ACTION_CODE_FATAL, + "error occurred while converting tunings from Java to native"); return; } @@ -2421,15 +2471,23 @@ static void android_media_MediaCodec_native_queueLinearBlock( } env->MonitorExit(lock.get()); } else { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary( + env, INVALID_OPERATION, ACTION_CODE_FATAL, + "Failed to grab lock for a LinearBlock object"); return; } AString errorDetailMsg; if (codec->hasCryptoOrDescrambler()) { if (!memory) { + // It means there was an unexpected failure in extractMemoryFromContext above ALOGI("queueLinearBlock: no ashmem memory for encrypted content"); - throwExceptionAsNecessary(env, BAD_VALUE); + throwExceptionAsNecessary( + env, BAD_VALUE, ACTION_CODE_FATAL, + "Unexpected error: the input buffer is not compatible with " + "the secure codec, and a fallback logic failed.\n" + "Suggestion: please try including the secure codec when calling " + "MediaCodec.LinearBlock#obtain method to obtain a compatible buffer."); return; } auto cryptoInfo = @@ -2453,14 +2511,22 @@ static void android_media_MediaCodec_native_queueLinearBlock( ALOGI_IF(err != OK, "queueEncryptedLinearBlock returned err = %d", err); } else { if (!buffer) { + // It means there was an unexpected failure in extractBufferFromContext above ALOGI("queueLinearBlock: no C2Buffer found"); - throwExceptionAsNecessary(env, BAD_VALUE); + throwExceptionAsNecessary( + env, BAD_VALUE, ACTION_CODE_FATAL, + "Unexpected error: the input buffer is not compatible with " + "the non-secure codec, and a fallback logic failed.\n" + "Suggestion: please do not include the secure codec when calling " + "MediaCodec.LinearBlock#obtain method to obtain a compatible buffer."); return; } err = codec->queueBuffer( index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg); } - throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, errorDetailMsg.c_str()); + throwExceptionAsNecessary( + env, err, ACTION_CODE_FATAL, + codec->getExceptionMessage(errorDetailMsg.c_str()).c_str()); } static void android_media_MediaCodec_native_queueHardwareBuffer( @@ -2471,14 +2537,16 @@ static void android_media_MediaCodec_native_queueHardwareBuffer( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } sp<AMessage> tunings; status_t err = ConvertKeyValueListsToAMessage(env, keys, values, &tunings); if (err != OK) { - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary( + env, err, ACTION_CODE_FATAL, + "error occurred while converting tunings from Java to native"); return; } @@ -2503,7 +2571,9 @@ static void android_media_MediaCodec_native_queueHardwareBuffer( ALOGW("Failed to wrap AHardwareBuffer into C2GraphicAllocation"); native_handle_close(handle); native_handle_delete(handle); - throwExceptionAsNecessary(env, BAD_VALUE); + throwExceptionAsNecessary( + env, BAD_VALUE, ACTION_CODE_FATAL, + "HardwareBuffer not recognized"); return; } std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc); @@ -2512,7 +2582,9 @@ static void android_media_MediaCodec_native_queueHardwareBuffer( AString errorDetailMsg; err = codec->queueBuffer( index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg); - throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, errorDetailMsg.c_str()); + throwExceptionAsNecessary( + env, err, ACTION_CODE_FATAL, + codec->getExceptionMessage(errorDetailMsg.c_str()).c_str()); } static void android_media_MediaCodec_native_getOutputFrame( @@ -2522,13 +2594,13 @@ static void android_media_MediaCodec_native_getOutputFrame( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t err = codec->getOutputFrame(env, frame, index); if (err != OK) { - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } } @@ -2539,7 +2611,7 @@ static jint android_media_MediaCodec_dequeueInputBuffer( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return -1; } @@ -2550,7 +2622,7 @@ static jint android_media_MediaCodec_dequeueInputBuffer( return (jint) index; } - return throwExceptionAsNecessary(env, err); + return throwExceptionAsNecessary(env, err, codec); } static jint android_media_MediaCodec_dequeueOutputBuffer( @@ -2560,7 +2632,7 @@ static jint android_media_MediaCodec_dequeueOutputBuffer( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return 0; } @@ -2572,7 +2644,7 @@ static jint android_media_MediaCodec_dequeueOutputBuffer( return (jint) index; } - return throwExceptionAsNecessary(env, err); + return throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_releaseOutputBuffer( @@ -2583,13 +2655,13 @@ static void android_media_MediaCodec_releaseOutputBuffer( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs); - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env, @@ -2598,13 +2670,13 @@ static void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env, sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t err = codec->signalEndOfInputStream(); - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static jobject android_media_MediaCodec_getFormatNative( @@ -2614,7 +2686,7 @@ static jobject android_media_MediaCodec_getFormatNative( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } @@ -2625,7 +2697,7 @@ static jobject android_media_MediaCodec_getFormatNative( return format; } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); return NULL; } @@ -2637,7 +2709,7 @@ static jobject android_media_MediaCodec_getOutputFormatForIndexNative( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } @@ -2648,7 +2720,7 @@ static jobject android_media_MediaCodec_getOutputFormatForIndexNative( return format; } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); return NULL; } @@ -2660,7 +2732,7 @@ static jobjectArray android_media_MediaCodec_getBuffers( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } @@ -2673,7 +2745,7 @@ static jobjectArray android_media_MediaCodec_getBuffers( // if we're out of memory, an exception was already thrown if (err != NO_MEMORY) { - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } return NULL; @@ -2686,7 +2758,7 @@ static jobject android_media_MediaCodec_getBuffer( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } @@ -2699,7 +2771,7 @@ static jobject android_media_MediaCodec_getBuffer( // if we're out of memory, an exception was already thrown if (err != NO_MEMORY) { - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } return NULL; @@ -2712,7 +2784,7 @@ static jobject android_media_MediaCodec_getImage( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } @@ -2725,7 +2797,7 @@ static jobject android_media_MediaCodec_getImage( // if we're out of memory, an exception was already thrown if (err != NO_MEMORY) { - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } return NULL; @@ -2738,7 +2810,7 @@ static jobject android_media_MediaCodec_getName( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } @@ -2749,7 +2821,7 @@ static jobject android_media_MediaCodec_getName( return name; } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); return NULL; } @@ -2761,7 +2833,7 @@ static jobject android_media_MediaCodec_getOwnCodecInfo( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } @@ -2772,7 +2844,7 @@ static jobject android_media_MediaCodec_getOwnCodecInfo( return codecInfoObj; } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); return NULL; } @@ -2784,7 +2856,8 @@ android_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz) sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); + jniThrowException(env, "java/lang/IllegalStateException", + GetExceptionMessage(codec, NULL).c_str()); return 0; } @@ -2813,7 +2886,7 @@ static void android_media_MediaCodec_setParameters( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } @@ -2824,7 +2897,7 @@ static void android_media_MediaCodec_setParameters( err = codec->setParameters(params); } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_setVideoScalingMode( @@ -2832,13 +2905,14 @@ static void android_media_MediaCodec_setVideoScalingMode( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowException(env, "java/lang/IllegalArgumentException", + String8::format("Unrecognized mode: %d", mode)); return; } @@ -2850,7 +2924,7 @@ static void android_media_MediaCodec_setAudioPresentation( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } @@ -2862,14 +2936,14 @@ static jobject android_media_MediaCodec_getSupportedVendorParameters( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } jobject ret = NULL; status_t status = codec->querySupportedVendorParameters(env, &ret); if (status != OK) { - throwExceptionAsNecessary(env, status); + throwExceptionAsNecessary(env, status, codec); } return ret; @@ -2880,7 +2954,7 @@ static jobject android_media_MediaCodec_getParameterDescriptor( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return NULL; } @@ -2897,13 +2971,13 @@ static void android_media_MediaCodec_subscribeToVendorParameters( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t status = codec->subscribeToVendorParameters(env, names); if (status != OK) { - throwExceptionAsNecessary(env, status); + throwExceptionAsNecessary(env, status, codec); } return; } @@ -2913,13 +2987,13 @@ static void android_media_MediaCodec_unsubscribeFromVendorParameters( sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL || codec->initCheck() != OK) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); return; } status_t status = codec->unsubscribeFromVendorParameters(env, names); if (status != OK) { - throwExceptionAsNecessary(env, status); + throwExceptionAsNecessary(env, status, codec); } return; } @@ -3310,11 +3384,15 @@ static jobject android_media_MediaCodec_LinearBlock_native_map( if (!context->mReadonlyMapping) { const C2BufferData data = buffer->data(); if (data.type() != C2BufferData::LINEAR) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary( + env, INVALID_OPERATION, ACTION_CODE_FATAL, + "Underlying buffer is not a linear buffer"); return nullptr; } if (data.linearBlocks().size() != 1u) { - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary( + env, INVALID_OPERATION, ACTION_CODE_FATAL, + "Underlying buffer contains more than one block"); return nullptr; } C2ConstLinearBlock block = data.linearBlocks().front(); @@ -3362,7 +3440,9 @@ static jobject android_media_MediaCodec_LinearBlock_native_map( false, // readOnly true /* clearBuffer */); } - throwExceptionAsNecessary(env, INVALID_OPERATION); + throwExceptionAsNecessary( + env, INVALID_OPERATION, ACTION_CODE_FATAL, + "Underlying buffer is empty"); return nullptr; } @@ -3385,7 +3465,9 @@ static void PopulateNamesVector( } const char *cstr = env->GetStringUTFChars(jstr, nullptr); if (cstr == nullptr) { - throwExceptionAsNecessary(env, BAD_VALUE); + throwExceptionAsNecessary( + env, BAD_VALUE, ACTION_CODE_FATAL, + "Error converting Java string to native"); return; } names->emplace_back(cstr); @@ -3437,6 +3519,7 @@ static jboolean android_media_MediaCodec_LinearBlock_checkCompatible( } status_t err = MediaCodec::CanFetchLinearBlock(names, &isCompatible); if (err != OK) { + // TODO: CodecErrorLog throwExceptionAsNecessary(env, err); } return isCompatible; diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index 616c31b29157..fbaf64fda572 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -176,6 +176,8 @@ struct JMediaCodec : public AHandler { const sp<ICrypto> &getCrypto() { return mCrypto; } + std::string getExceptionMessage(const char *msg) const; + protected: virtual ~JMediaCodec(); diff --git a/media/jni/android_media_MediaCodecLinearBlock.h b/media/jni/android_media_MediaCodecLinearBlock.h index c7530207d1fa..060abfdc1ee5 100644 --- a/media/jni/android_media_MediaCodecLinearBlock.h +++ b/media/jni/android_media_MediaCodecLinearBlock.h @@ -44,12 +44,19 @@ struct JMediaCodecLinearBlock { std::shared_ptr<C2Buffer> toC2Buffer(size_t offset, size_t size) const { if (mBuffer) { + // TODO: if returned C2Buffer is different from mBuffer, we should + // find a way to connect the life cycle between this C2Buffer and + // mBuffer. if (mBuffer->data().type() != C2BufferData::LINEAR) { return nullptr; } C2ConstLinearBlock block = mBuffer->data().linearBlocks().front(); if (offset == 0 && size == block.capacity()) { - return mBuffer; + // Let C2Buffer be new one to queue to MediaCodec. It will allow + // the related input slot to be released by onWorkDone from C2 + // Component. Currently, the life cycle of mBuffer should be + // protected by different flows. + return std::make_shared<C2Buffer>(*mBuffer); } std::shared_ptr<C2Buffer> buffer = diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml index 176534829222..cd404385d5a0 100644 --- a/packages/DynamicSystemInstallationService/AndroidManifest.xml +++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml @@ -39,6 +39,10 @@ <data android:scheme="http" /> <data android:scheme="https" /> </intent-filter> + <intent-filter> + <action android:name="android.os.image.action.START_INSTALL" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> </activity> <receiver diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index 55626844594d..5e42f705cf4b 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -19,6 +19,7 @@ package com.android.dynsystem; import static android.os.AsyncTask.Status.FINISHED; import static android.os.AsyncTask.Status.PENDING; import static android.os.AsyncTask.Status.RUNNING; +import static android.os.image.DynamicSystemClient.ACTION_HIDE_NOTIFICATION; import static android.os.image.DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE; import static android.os.image.DynamicSystemClient.ACTION_START_INSTALL; import static android.os.image.DynamicSystemClient.CAUSE_ERROR_EXCEPTION; @@ -27,6 +28,8 @@ import static android.os.image.DynamicSystemClient.CAUSE_ERROR_IO; import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_CANCELLED; import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_COMPLETED; import static android.os.image.DynamicSystemClient.CAUSE_NOT_SPECIFIED; +import static android.os.image.DynamicSystemClient.KEY_ENABLE_WHEN_COMPLETED; +import static android.os.image.DynamicSystemClient.KEY_ONE_SHOT; import static android.os.image.DynamicSystemClient.STATUS_IN_PROGRESS; import static android.os.image.DynamicSystemClient.STATUS_IN_USE; import static android.os.image.DynamicSystemClient.STATUS_NOT_STARTED; @@ -77,8 +80,6 @@ public class DynamicSystemInstallationService extends Service private static final String TAG = "DynamicSystemInstallationService"; - // TODO (b/131866826): This is currently for test only. Will move this to System API. - static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED"; static final String KEY_DSU_SLOT = "KEY_DSU_SLOT"; static final String DEFAULT_DSU_SLOT = "dsu"; static final String KEY_PUBKEY = "KEY_PUBKEY"; @@ -172,6 +173,8 @@ public class DynamicSystemInstallationService extends Service // This is for testing only now private boolean mEnableWhenCompleted; + private boolean mOneShot; + private boolean mHideNotification; private InstallationAsyncTask.Progress mInstallTaskProgress; private InstallationAsyncTask mInstallTask; @@ -229,6 +232,8 @@ public class DynamicSystemInstallationService extends Service executeRebootToNormalCommand(); } else if (ACTION_NOTIFY_IF_IN_USE.equals(action)) { executeNotifyIfInUseCommand(); + } else if (ACTION_HIDE_NOTIFICATION.equals(action)) { + executeHideNotificationCommand(); } return Service.START_NOT_STICKY; @@ -318,6 +323,7 @@ public class DynamicSystemInstallationService extends Service long systemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0); long userdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0); mEnableWhenCompleted = intent.getBooleanExtra(KEY_ENABLE_WHEN_COMPLETED, false); + mOneShot = intent.getBooleanExtra(KEY_ONE_SHOT, true); String dsuSlot = intent.getStringExtra(KEY_DSU_SLOT); String publicKey = intent.getStringExtra(KEY_PUBKEY); @@ -384,9 +390,9 @@ public class DynamicSystemInstallationService extends Service boolean enabled = false; if (mInstallTask != null && mInstallTask.isCompleted()) { - enabled = mInstallTask.commit(); + enabled = mInstallTask.commit(mOneShot); } else if (isDynamicSystemInstalled()) { - enabled = mDynSystem.setEnable(true, true); + enabled = mDynSystem.setEnable(true, mOneShot); } else { Log.e(TAG, "Trying to reboot to AOT while there is no complete installation"); return; @@ -439,12 +445,16 @@ public class DynamicSystemInstallationService extends Service private void executeNotifyIfInUseCommand() { switch (getStatus()) { case STATUS_IN_USE: - startForeground(NOTIFICATION_ID, - buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED)); + if (!mHideNotification) { + startForeground(NOTIFICATION_ID, + buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED)); + } break; case STATUS_READY: - startForeground(NOTIFICATION_ID, - buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED)); + if (!mHideNotification) { + startForeground(NOTIFICATION_ID, + buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED)); + } break; case STATUS_IN_PROGRESS: break; @@ -454,6 +464,16 @@ public class DynamicSystemInstallationService extends Service } } + private void executeHideNotificationCommand() { + mHideNotification = true; + switch (getStatus()) { + case STATUS_IN_USE: + case STATUS_READY: + stopForeground(STOP_FOREGROUND_REMOVE); + break; + } + } + private void resetTaskAndStop() { resetTaskAndStop(/* removeNotification= */ false); } diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java index a41399fb0d0d..42b620abe734 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java @@ -803,7 +803,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { return mIsCompleted; } - boolean commit() { - return mDynSystem.setEnable(true, true); + boolean commit(boolean oneShot) { + return mDynSystem.setEnable(true, oneShot); } } diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java index 64e42cc595ec..b52272961e4b 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java @@ -16,6 +16,8 @@ package com.android.dynsystem; +import static android.os.image.DynamicSystemClient.KEY_KEYGUARD_USE_DEFAULT_STRINGS; + import android.app.Activity; import android.app.KeyguardManager; import android.content.Context; @@ -47,10 +49,7 @@ public class VerificationActivity extends Activity { KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); if (km != null) { - String title = getString(R.string.keyguard_title); - String description = getString(R.string.keyguard_description); - Intent intent = km.createConfirmDeviceCredentialIntent(title, description); - + Intent intent = createConfirmDeviceCredentialIntent(km); if (intent == null) { Log.d(TAG, "This device is not protected by a password/pin"); startInstallationService(); @@ -63,6 +62,23 @@ public class VerificationActivity extends Activity { } } + private Intent createConfirmDeviceCredentialIntent(KeyguardManager km) { + final boolean useDefaultStrings = + getIntent().getBooleanExtra(KEY_KEYGUARD_USE_DEFAULT_STRINGS, false); + final String title; + final String description; + if (useDefaultStrings) { + // Use default strings provided by keyguard manager + title = null; + description = null; + } else { + // Use custom strings provided by DSU + title = getString(R.string.keyguard_title); + description = getString(R.string.keyguard_description); + } + return km.createConfirmDeviceCredentialIntent(title, description); + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) { diff --git a/packages/PrintSpooler/tests/outofprocess/Android.bp b/packages/PrintSpooler/tests/outofprocess/Android.bp index 69a1d7fa59e4..ef0d122c7273 100644 --- a/packages/PrintSpooler/tests/outofprocess/Android.bp +++ b/packages/PrintSpooler/tests/outofprocess/Android.bp @@ -31,7 +31,7 @@ android_test { libs: ["android.test.runner.stubs"], static_libs: [ "androidx.test.rules", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", "mockito-target-minus-junit4", "print-test-util-lib", ], diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java index 132545b2d5d2..1509b7077046 100644 --- a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java +++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java @@ -35,15 +35,15 @@ import android.print.test.services.AddPrintersActivity; import android.print.test.services.FirstPrintService; import android.print.test.services.PrinterDiscoverySessionCallbacks; import android.print.test.services.StubbablePrinterDiscoverySession; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.UiSelector; -import android.support.test.uiautomator.Until; import android.util.Log; import androidx.test.filters.LargeTest; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; +import androidx.test.uiautomator.Until; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/packages/SettingsProvider/src/android/provider/settings/OWNERS b/packages/SettingsProvider/src/android/provider/settings/OWNERS index 0f888113d730..d901e2cec358 100644 --- a/packages/SettingsProvider/src/android/provider/settings/OWNERS +++ b/packages/SettingsProvider/src/android/provider/settings/OWNERS @@ -1,4 +1,4 @@ # Bug component: 656484 -include platform/frameworks/base:/services/backup/OWNERS +include platform/frameworks/base:/services/backup/BACKUP_OWNERS diff --git a/packages/SettingsProvider/test/src/android/provider/OWNERS b/packages/SettingsProvider/test/src/android/provider/OWNERS index 0f888113d730..db4b27c8bc5a 100644 --- a/packages/SettingsProvider/test/src/android/provider/OWNERS +++ b/packages/SettingsProvider/test/src/android/provider/OWNERS @@ -1,4 +1,3 @@ # Bug component: 656484 -include platform/frameworks/base:/services/backup/OWNERS - +include platform/frameworks/base:/services/backup/BACKUP_OWNERS diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt index 0f81b0b8d6e0..3889030d5566 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt @@ -298,10 +298,16 @@ constructor( ) { val view = openedDialogs.firstOrNull { it.dialog == animateFrom }?.dialogContentWithBackground - ?: throw IllegalStateException( - "The animateFrom dialog was not animated using " + - "DialogLaunchAnimator.showFrom(View|Dialog)" - ) + if (view == null) { + Log.w( + TAG, + "Showing dialog $dialog normally as the dialog it is shown from was not shown " + + "using DialogLaunchAnimator" + ) + dialog.show() + return + } + showFromView( dialog, view, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 93027c1914ee..e7aa176e5d68 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2735,7 +2735,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab boolean shouldListen = shouldListenKeyguardState && shouldListenUserState && shouldListenBouncerState && shouldListenUdfpsState - && shouldListenSideFpsState; + && shouldListenSideFpsState + && !isFingerprintLockedOut(); logListenerModelData( new KeyguardFingerprintListenModel( System.currentTimeMillis(), diff --git a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java index 05e566690f57..29f16c7b924a 100644 --- a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java +++ b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java @@ -272,10 +272,10 @@ public class SystemUIToast implements ToastPlugin.Toast { private static boolean showApplicationIcon(ApplicationInfo appInfo, PackageManager packageManager) { - if (hasFlag(appInfo.flags, FLAG_UPDATED_SYSTEM_APP)) { + if (hasFlag(appInfo.flags, FLAG_UPDATED_SYSTEM_APP | FLAG_SYSTEM)) { return packageManager.getLaunchIntentForPackage(appInfo.packageName) != null; } - return !hasFlag(appInfo.flags, FLAG_SYSTEM); + return true; } private static boolean hasFlag(int flags, int flag) { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 13cd328d00e0..73e11d7ef833 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -28,6 +28,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOM import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED; +import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING; import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT; import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT; @@ -1040,10 +1041,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked); assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked); - // Fingerprint should be restarted once its cancelled bc on lockout, the device - // can still detectFingerprint (and if it's not locked out, fingerprint can listen) + // Fingerprint should be cancelled on lockout if going to lockout state, else + // restarted if it's not assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState) - .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING); + .isEqualTo(fpLocked + ? BIOMETRIC_STATE_CANCELLING : BIOMETRIC_STATE_CANCELLING_RESTARTING); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt index cac4a0e5432c..82af0f418ea4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt @@ -260,6 +260,12 @@ class DialogLaunchAnimatorTest : SysuiTestCase() { assertThat(touchSurface.visibility).isEqualTo(View.GONE) } + @Test + fun showFromDialogDoesNotCrashWhenShownFromRandomDialog() { + val dialog = createDialogAndShowFromDialog(animateFrom = TestDialog(context)) + dialog.dismiss() + } + private fun createAndShowDialog( animator: DialogLaunchAnimator = dialogLaunchAnimator, ): TestDialog { diff --git a/services/backup/BACKUP_OWNERS b/services/backup/BACKUP_OWNERS new file mode 100644 index 000000000000..f8f4f4f4bf2e --- /dev/null +++ b/services/backup/BACKUP_OWNERS @@ -0,0 +1,10 @@ +# Bug component: 1193469 + +jstemmer@google.com +martinoh@google.com +millmore@google.com +niamhfw@google.com +piee@google.com +philippov@google.com +rthakohov@google.com +sarpm@google.com
\ No newline at end of file diff --git a/services/backup/OWNERS b/services/backup/OWNERS index 79709a3319c8..3bd2db13eea1 100644 --- a/services/backup/OWNERS +++ b/services/backup/OWNERS @@ -2,12 +2,4 @@ set noparent -bryanmawhinney@google.com -jstemmer@google.com -martinoh@google.com -millmore@google.com -niamhfw@google.com -piee@google.com -philippov@google.com -rthakohov@google.com -sarpm@google.com +include platform/frameworks/base:/services/backup/BACKUP_OWNERS diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 409f0541eed7..123cd3288343 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -27,6 +27,7 @@ per-file **IpSec* = file:/services/core/java/com/android/server/net/OWNERS per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS +per-file *SoundTrigger* = file:/media/java/android/media/soundtrigger/OWNERS per-file *Storage* = file:/core/java/android/os/storage/OWNERS per-file *TimeUpdate* = file:/services/core/java/com/android/server/timezonedetector/OWNERS per-file DynamicSystemService.java = file:/packages/DynamicSystemInstallationService/OWNERS diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 89447b457c20..f8467410b3ba 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -3091,7 +3091,7 @@ public class AccountManagerService } } - Intent intent = result.getParcelable(AccountManager.KEY_INTENT); + Intent intent = result.getParcelable(AccountManager.KEY_INTENT, Intent.class); if (intent != null && notifyOnAuthFailure && !customTokens) { /* * Make sure that the supplied intent is owned by the authenticator @@ -3516,8 +3516,7 @@ public class AccountManagerService Bundle.setDefusable(result, true); mNumResults++; Intent intent = null; - if (result != null - && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { + if (result != null) { if (!checkKeyIntent( Binder.getCallingUid(), result)) { @@ -4886,8 +4885,10 @@ public class AccountManagerService EventLog.writeEvent(0x534e4554, "250588548", authUid, ""); return false; } - Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class); + if (intent == null) { + return true; + } // Explicitly set an empty ClipData to ensure that we don't offer to // promote any Uris contained inside for granting purposes if (intent.getClipData() == null) { @@ -4937,8 +4938,12 @@ public class AccountManagerService Bundle simulateBundle = p.readBundle(); p.recycle(); Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class); - return (intent.filterEquals(simulateBundle.getParcelable(AccountManager.KEY_INTENT, - Intent.class))); + Intent simulateIntent = simulateBundle.getParcelable(AccountManager.KEY_INTENT, + Intent.class); + if (intent == null) { + return (simulateIntent == null); + } + return intent.filterEquals(simulateIntent); } private boolean isExportedSystemActivity(ActivityInfo activityInfo) { @@ -5087,8 +5092,7 @@ public class AccountManagerService } } } - if (result != null - && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { + if (result != null) { if (!checkKeyIntent( Binder.getCallingUid(), result)) { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 9669c060b716..c36e0700c723 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -3420,6 +3420,11 @@ public final class ActiveServices { throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + className + " is not an isolatedProcess"); } + if (!mAm.getPackageManagerInternal().isSameApp(callingPackage, callingUid, + userId)) { + throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + + "calling package not owned by calling UID "); + } // Run the service under the calling package's application. ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo( callingPackage, ActivityManagerService.STOCK_PM_FLAGS, userId); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 99f186351f0f..0eda49e6b874 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8496,7 +8496,9 @@ public class ActivityManagerService extends IActivityManager.Stub // 'recoverable' is that the app doesn't crash). Normally, for nonrecoreable native crashes, // debuggerd will terminate the process, but there's a backup where ActivityManager will // also kill it. Avoid that. - if (!recoverable) { + if (recoverable) { + mAppErrors.sendRecoverableCrashToAppExitInfo(r, crashInfo); + } else { mAppErrors.crashApplication(r, crashInfo); } } @@ -14666,6 +14668,17 @@ public class ActivityManagerService extends IActivityManager.Stub throw new SecurityException(msg); } } + if (!Build.IS_DEBUGGABLE && callingUid != ROOT_UID && callingUid != SHELL_UID + && callingUid != SYSTEM_UID && !hasActiveInstrumentationLocked(callingPid)) { + // If it's not debug build and not called from root/shell/system uid, reject it. + final String msg = "Permission Denial: instrumentation test " + + className + " from pid=" + callingPid + ", uid=" + callingUid + + ", pkgName=" + getPackageNameByPid(callingPid) + + " not allowed because it's not started from SHELL"; + Slog.wtfQuiet(TAG, msg); + reportStartInstrumentationFailureLocked(watcher, className, msg); + throw new SecurityException(msg); + } boolean disableHiddenApiChecks = ai.usesNonSdkApi() || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0; @@ -14888,6 +14901,29 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") + private boolean hasActiveInstrumentationLocked(int pid) { + if (pid == 0) { + return false; + } + synchronized (mPidsSelfLocked) { + ProcessRecord process = mPidsSelfLocked.get(pid); + return process != null && process.getActiveInstrumentation() != null; + } + } + + private String getPackageNameByPid(int pid) { + synchronized (mPidsSelfLocked) { + final ProcessRecord app = mPidsSelfLocked.get(pid); + + if (app != null && app.info != null) { + return app.info.packageName; + } + + return null; + } + } + private boolean isCallerShell() { final int callingUid = Binder.getCallingUid(); return callingUid == SHELL_UID || callingUid == ROOT_UID; diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 08c1de61d7fb..c475f008c831 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -553,6 +553,15 @@ class AppErrors { } } + void sendRecoverableCrashToAppExitInfo( + ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { + if (r == null || crashInfo == null + || !"Native crash".equals(crashInfo.exceptionClassName)) return; + synchronized (mService) { + mService.mProcessList.noteAppRecoverableCrash(r); + } + } + /** * Bring up the "unexpected error" dialog box for a crashing app. * Deal with edge cases (intercepts from instrumented applications, diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java index 32d20718c192..df1f3c7ec774 100644 --- a/services/core/java/com/android/server/am/AppExitInfoTracker.java +++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java @@ -308,6 +308,16 @@ public final class AppExitInfoTracker { mKillHandler.obtainMessage(KillHandler.MSG_APP_KILL, raw).sendToTarget(); } + void scheduleNoteAppRecoverableCrash(final ProcessRecord app) { + if (!mAppExitInfoLoaded.get() || app == null || app.info == null) return; + + ApplicationExitInfo raw = obtainRawRecord(app, System.currentTimeMillis()); + raw.setReason(ApplicationExitInfo.REASON_CRASH_NATIVE); + raw.setSubReason(ApplicationExitInfo.SUBREASON_UNKNOWN); + raw.setDescription("recoverable_crash"); + mKillHandler.obtainMessage(KillHandler.MSG_APP_RECOVERABLE_CRASH, raw).sendToTarget(); + } + void scheduleNoteAppKill(final int pid, final int uid, final @Reason int reason, final @SubReason int subReason, final String msg) { if (!mAppExitInfoLoaded.get()) { @@ -421,8 +431,24 @@ public final class AppExitInfoTracker { scheduleLogToStatsdLocked(info, true); } + /** + * Make note when ActivityManagerService gets a recoverable native crash, as the process isn't + * being killed but the crash should still be added to AppExitInfo. Also, because we're not + * crashing, don't log out to statsd. + */ + @VisibleForTesting + @GuardedBy("mLock") + void handleNoteAppRecoverableCrashLocked(final ApplicationExitInfo raw) { + addExitInfoLocked(raw, /* recoverable */ true); + } + @GuardedBy("mLock") private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw) { + return addExitInfoLocked(raw, /* recoverable */ false); + } + + @GuardedBy("mLock") + private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw, boolean recoverable) { if (!mAppExitInfoLoaded.get()) { Slog.w(TAG, "Skipping saving the exit info due to ongoing loading from storage"); return null; @@ -438,7 +464,7 @@ public final class AppExitInfoTracker { } } for (int i = 0; i < packages.length; i++) { - addExitInfoInnerLocked(packages[i], uid, info); + addExitInfoInnerLocked(packages[i], uid, info, recoverable); } schedulePersistProcessExitInfo(false); @@ -845,7 +871,8 @@ public final class AppExitInfoTracker { } @GuardedBy("mLock") - private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info) { + private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info, + boolean recoverable) { AppExitInfoContainer container = mData.get(packageName, uid); if (container == null) { container = new AppExitInfoContainer(mAppExitInfoHistoryListSize); @@ -859,7 +886,11 @@ public final class AppExitInfoTracker { } mData.put(packageName, uid, container); } - container.addExitInfoLocked(info); + if (recoverable) { + container.addRecoverableCrashLocked(info); + } else { + container.addExitInfoLocked(info); + } } @GuardedBy("mLock") @@ -1284,38 +1315,40 @@ public final class AppExitInfoTracker { * A container class of {@link android.app.ApplicationExitInfo} */ final class AppExitInfoContainer { - private SparseArray<ApplicationExitInfo> mInfos; // index is pid + private SparseArray<ApplicationExitInfo> mInfos; // index is a pid + private SparseArray<ApplicationExitInfo> mRecoverableCrashes; // index is a pid private int mMaxCapacity; private int mUid; // Application uid, not isolated uid. AppExitInfoContainer(final int maxCapacity) { mInfos = new SparseArray<ApplicationExitInfo>(); + mRecoverableCrashes = new SparseArray<ApplicationExitInfo>(); mMaxCapacity = maxCapacity; } @GuardedBy("mLock") - void getExitInfoLocked(final int filterPid, final int maxNum, - ArrayList<ApplicationExitInfo> results) { + void getInfosLocked(SparseArray<ApplicationExitInfo> map, final int filterPid, + final int maxNum, ArrayList<ApplicationExitInfo> results) { if (filterPid > 0) { - ApplicationExitInfo r = mInfos.get(filterPid); + ApplicationExitInfo r = map.get(filterPid); if (r != null) { results.add(r); } } else { - final int numRep = mInfos.size(); + final int numRep = map.size(); if (maxNum <= 0 || numRep <= maxNum) { // Return all records. for (int i = 0; i < numRep; i++) { - results.add(mInfos.valueAt(i)); + results.add(map.valueAt(i)); } Collections.sort(results, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp())); } else { if (maxNum == 1) { // Most of the caller might be only interested with the most recent one - ApplicationExitInfo r = mInfos.valueAt(0); + ApplicationExitInfo r = map.valueAt(0); for (int i = 1; i < numRep; i++) { - ApplicationExitInfo t = mInfos.valueAt(i); + ApplicationExitInfo t = map.valueAt(i); if (r.getTimestamp() < t.getTimestamp()) { r = t; } @@ -1326,7 +1359,7 @@ public final class AppExitInfoTracker { ArrayList<ApplicationExitInfo> list = mTmpInfoList2; list.clear(); for (int i = 0; i < numRep; i++) { - list.add(mInfos.valueAt(i)); + list.add(map.valueAt(i)); } Collections.sort(list, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp())); @@ -1340,24 +1373,30 @@ public final class AppExitInfoTracker { } @GuardedBy("mLock") - void addExitInfoLocked(ApplicationExitInfo info) { + void getExitInfoLocked(final int filterPid, final int maxNum, + ArrayList<ApplicationExitInfo> results) { + getInfosLocked(mInfos, filterPid, maxNum, results); + } + + @GuardedBy("mLock") + void addInfoLocked(SparseArray<ApplicationExitInfo> map, ApplicationExitInfo info) { int size; - if ((size = mInfos.size()) >= mMaxCapacity) { + if ((size = map.size()) >= mMaxCapacity) { int oldestIndex = -1; long oldestTimeStamp = Long.MAX_VALUE; for (int i = 0; i < size; i++) { - ApplicationExitInfo r = mInfos.valueAt(i); + ApplicationExitInfo r = map.valueAt(i); if (r.getTimestamp() < oldestTimeStamp) { oldestTimeStamp = r.getTimestamp(); oldestIndex = i; } } if (oldestIndex >= 0) { - final File traceFile = mInfos.valueAt(oldestIndex).getTraceFile(); + final File traceFile = map.valueAt(oldestIndex).getTraceFile(); if (traceFile != null) { traceFile.delete(); } - mInfos.removeAt(oldestIndex); + map.removeAt(oldestIndex); } } // Claim the state information if there is any @@ -1367,7 +1406,17 @@ public final class AppExitInfoTracker { mActiveAppStateSummary, uid, pid)); info.setTraceFile(findAndRemoveFromSparse2dArray(mActiveAppTraces, uid, pid)); info.setAppTraceRetriever(mAppTraceRetriever); - mInfos.append(pid, info); + map.append(pid, info); + } + + @GuardedBy("mLock") + void addExitInfoLocked(ApplicationExitInfo info) { + addInfoLocked(mInfos, info); + } + + @GuardedBy("mLock") + void addRecoverableCrashLocked(ApplicationExitInfo info) { + addInfoLocked(mRecoverableCrashes, info); } @GuardedBy("mLock") @@ -1382,9 +1431,9 @@ public final class AppExitInfoTracker { } @GuardedBy("mLock") - void destroyLocked() { - for (int i = mInfos.size() - 1; i >= 0; i--) { - ApplicationExitInfo ai = mInfos.valueAt(i); + void destroyLocked(SparseArray<ApplicationExitInfo> map) { + for (int i = map.size() - 1; i >= 0; i--) { + ApplicationExitInfo ai = map.valueAt(i); final File traceFile = ai.getTraceFile(); if (traceFile != null) { traceFile.delete(); @@ -1395,24 +1444,37 @@ public final class AppExitInfoTracker { } @GuardedBy("mLock") + void destroyLocked() { + destroyLocked(mInfos); + destroyLocked(mRecoverableCrashes); + } + + @GuardedBy("mLock") void forEachRecordLocked(final BiFunction<Integer, ApplicationExitInfo, Integer> callback) { - if (callback != null) { - for (int i = mInfos.size() - 1; i >= 0; i--) { - switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) { - case FOREACH_ACTION_REMOVE_ITEM: - final File traceFile = mInfos.valueAt(i).getTraceFile(); - if (traceFile != null) { - traceFile.delete(); - } - mInfos.removeAt(i); - break; - case FOREACH_ACTION_STOP_ITERATION: - i = 0; - break; - case FOREACH_ACTION_NONE: - default: - break; - } + if (callback == null) return; + for (int i = mInfos.size() - 1; i >= 0; i--) { + switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) { + case FOREACH_ACTION_STOP_ITERATION: return; + case FOREACH_ACTION_REMOVE_ITEM: + final File traceFile = mInfos.valueAt(i).getTraceFile(); + if (traceFile != null) { + traceFile.delete(); + } + mInfos.removeAt(i); + break; + } + } + for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) { + switch (callback.apply( + mRecoverableCrashes.keyAt(i), mRecoverableCrashes.valueAt(i))) { + case FOREACH_ACTION_STOP_ITERATION: return; + case FOREACH_ACTION_REMOVE_ITEM: + final File traceFile = mRecoverableCrashes.valueAt(i).getTraceFile(); + if (traceFile != null) { + traceFile.delete(); + } + mRecoverableCrashes.removeAt(i); + break; } } } @@ -1423,6 +1485,9 @@ public final class AppExitInfoTracker { for (int i = mInfos.size() - 1; i >= 0; i--) { list.add(mInfos.valueAt(i)); } + for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) { + list.add(mRecoverableCrashes.valueAt(i)); + } Collections.sort(list, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp())); int size = list.size(); for (int i = 0; i < size; i++) { @@ -1434,10 +1499,13 @@ public final class AppExitInfoTracker { void writeToProto(ProtoOutputStream proto, long fieldId) { long token = proto.start(fieldId); proto.write(AppsExitInfoProto.Package.User.UID, mUid); - int size = mInfos.size(); - for (int i = 0; i < size; i++) { + for (int i = 0; i < mInfos.size(); i++) { mInfos.valueAt(i).writeToProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO); } + for (int i = 0; i < mRecoverableCrashes.size(); i++) { + mRecoverableCrashes.valueAt(i).writeToProto( + proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH); + } proto.end(token); } @@ -1448,14 +1516,23 @@ public final class AppExitInfoTracker { next != ProtoInputStream.NO_MORE_FIELDS; next = proto.nextField()) { switch (next) { - case (int) AppsExitInfoProto.Package.User.UID: + case (int) AppsExitInfoProto.Package.User.UID: { mUid = proto.readInt(AppsExitInfoProto.Package.User.UID); break; - case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO: + } + case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO: { ApplicationExitInfo info = new ApplicationExitInfo(); info.readFromProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO); mInfos.put(info.getPid(), info); break; + } + case (int) AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH: { + ApplicationExitInfo info = new ApplicationExitInfo(); + info.readFromProto( + proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH); + mRecoverableCrashes.put(info.getPid(), info); + break; + } } } proto.end(token); @@ -1472,6 +1549,11 @@ public final class AppExitInfoTracker { list.add(mInfos.valueAt(i)); } } + for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) { + if (filterPid == 0 || filterPid == mRecoverableCrashes.keyAt(i)) { + list.add(mRecoverableCrashes.valueAt(i)); + } + } return list; } } @@ -1610,6 +1692,7 @@ public final class AppExitInfoTracker { static final int MSG_PROC_DIED = 4103; static final int MSG_APP_KILL = 4104; static final int MSG_STATSD_LOG = 4105; + static final int MSG_APP_RECOVERABLE_CRASH = 4106; KillHandler(Looper looper) { super(looper, null, true); @@ -1648,6 +1731,14 @@ public final class AppExitInfoTracker { } } break; + case MSG_APP_RECOVERABLE_CRASH: { + ApplicationExitInfo raw = (ApplicationExitInfo) msg.obj; + synchronized (mLock) { + handleNoteAppRecoverableCrashLocked(raw); + } + recycleRawRecord(raw); + } + break; default: super.handleMessage(msg); } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 256df98ae760..d0607d567900 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -105,6 +105,7 @@ import android.os.Trace; import android.os.UserHandle; import android.os.storage.StorageManagerInternal; import android.system.Os; +import android.system.OsConstants; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -2328,9 +2329,15 @@ public final class ProcessList { if (!regularZygote) { // webview and app zygote don't have the permission to create the nodes - if (Process.createProcessGroup(uid, startResult.pid) < 0) { - throw new AssertionError("Unable to create process group for " + app.processName - + " (" + startResult.pid + ")"); + final int res = Process.createProcessGroup(uid, startResult.pid); + if (res < 0) { + if (res == -OsConstants.ESRCH) { + Slog.e(ActivityManagerService.TAG, "Unable to create process group for " + + app.processName + " (" + startResult.pid + ")"); + } else { + throw new AssertionError("Unable to create process group for " + + app.processName + " (" + startResult.pid + ")"); + } } } @@ -5086,6 +5093,17 @@ public final class ProcessList { } /** + * Called by ActivityManagerService when a recoverable native crash occurs. + */ + @GuardedBy("mService") + void noteAppRecoverableCrash(final ProcessRecord app) { + if (DEBUG_PROCESSES) { + Slog.i(TAG, "note: " + app + " has a recoverable native crash"); + } + mAppExitInfoTracker.scheduleNoteAppRecoverableCrash(app); + } + + /** * Called by ActivityManagerService when it decides to kill an application process. */ @GuardedBy("mService") diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index 8886f0a06a52..b8ff26ea3cc9 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -98,7 +98,6 @@ public class SettingsToPropertiesMapper { DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, DeviceConfig.NAMESPACE_SURFACE_FLINGER_NATIVE_BOOT, DeviceConfig.NAMESPACE_SWCODEC_NATIVE, - DeviceConfig.NAMESPACE_TETHERING, DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE, DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE_BOOT, DeviceConfig.NAMESPACE_VIRTUALIZATION_FRAMEWORK_NATIVE, diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index a7c2ddf1b9d3..66682cceb3f0 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -7238,6 +7238,7 @@ public class AudioService extends IAudioService.Stub DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE); DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_LINE); DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET); + DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET); DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET); DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_HDMI); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 598e2b990ea5..94b67cedf86c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -452,6 +452,13 @@ public class FingerprintService extends SystemService { return -1; } + if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) { + // If this happens, something in KeyguardUpdateMonitor is wrong. This should only + // ever be invoked when the user is encrypted or lockdown. + Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown"); + return -1; + } + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for detectFingerprint"); diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index b25206d3b621..1dc2725feb1b 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -152,6 +152,7 @@ import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.BinderUtils; +import com.android.net.module.util.LinkPropertiesUtils; import com.android.net.module.util.NetdUtils; import com.android.net.module.util.NetworkStackConstants; import com.android.server.DeviceIdleInternal; @@ -230,7 +231,35 @@ public class Vpn { * <p>If retries have exceeded the length of this array, the last entry in the array will be * used as a repeating interval. */ - private static final long[] IKEV2_VPN_RETRY_DELAYS_SEC = {1L, 2L, 5L, 30L, 60L, 300L, 900L}; + private static final long[] IKEV2_VPN_RETRY_DELAYS_MS = + {1_000L, 2_000L, 5_000L, 30_000L, 60_000L, 300_000L, 900_000L}; + + /** + * A constant to pass to {@link IkeV2VpnRunner#scheduleStartIkeSession(long)} to mean the + * delay should be computed automatically with backoff. + */ + private static final long RETRY_DELAY_AUTO_BACKOFF = -1; + + /** + * How long to wait before trying to migrate the IKE connection when NetworkCapabilities or + * LinkProperties change in a way that may require migration. + * + * This delay is useful to avoid multiple migration tries (e.g. when a network changes + * both its NC and LP at the same time, e.g. when it first connects) and to minimize the + * cases where an old list of addresses is detected for the network. + * + * In practice, the IKE library reads the LinkProperties of the passed network with + * the synchronous {@link ConnectivityManager#getLinkProperties(Network)}, which means in + * most cases the race would resolve correctly, but this delay increases the chance that + * it correctly is. + * Further, using the synchronous method in the IKE library is actually dangerous because + * it is racy (it races with {@code IkeNetworkCallbackBase#onLost} and it should be fixed + * by using callbacks instead. When that happens, the race within IKE is fixed but the + * race between that callback and the one in IkeV2VpnRunner becomes a much bigger problem, + * and this delay will be necessary to ensure the correct link address list is used. + */ + private static final long IKE_DELAY_ON_NC_LP_CHANGE_MS = 300; + /** * Largest profile size allowable for Platform VPNs. * @@ -619,14 +648,14 @@ public class Vpn { /** * Retrieves the next retry delay * - * <p>If retries have exceeded the IKEV2_VPN_RETRY_DELAYS_SEC, the last entry in + * <p>If retries have exceeded the size of IKEV2_VPN_RETRY_DELAYS_MS, the last entry in * the array will be used as a repeating interval. */ - public long getNextRetryDelaySeconds(int retryCount) { - if (retryCount >= IKEV2_VPN_RETRY_DELAYS_SEC.length) { - return IKEV2_VPN_RETRY_DELAYS_SEC[IKEV2_VPN_RETRY_DELAYS_SEC.length - 1]; + public long getNextRetryDelayMs(int retryCount) { + if (retryCount >= IKEV2_VPN_RETRY_DELAYS_MS.length) { + return IKEV2_VPN_RETRY_DELAYS_MS[IKEV2_VPN_RETRY_DELAYS_MS.length - 1]; } else { - return IKEV2_VPN_RETRY_DELAYS_SEC[retryCount]; + return IKEV2_VPN_RETRY_DELAYS_MS[retryCount]; } } @@ -679,6 +708,14 @@ public class Vpn { boolean isIpv4) { return MtuUtils.getMtu(childProposals, maxMtu, underlyingMtu, isIpv4); } + + /** Verify the binder calling UID is the one passed in arguments */ + public void verifyCallingUidAndPackage(Context context, String packageName, int userId) { + final int callingUid = Binder.getCallingUid(); + if (getAppUid(context, packageName, userId) != callingUid) { + throw new SecurityException(packageName + " does not belong to uid " + callingUid); + } + } } @VisibleForTesting @@ -726,7 +763,7 @@ public class Vpn { mUserManager = mContext.getSystemService(UserManager.class); mPackage = VpnConfig.LEGACY_VPN; - mOwnerUID = getAppUid(mPackage, mUserId); + mOwnerUID = getAppUid(mContext, mPackage, mUserId); mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage); try { @@ -823,7 +860,7 @@ public class Vpn { } /** - * Chooses whether to force all connections to go though VPN. + * Chooses whether to force all connections to go through VPN. * * Used to enable/disable legacy VPN lockdown. * @@ -831,7 +868,7 @@ public class Vpn { * {@link #setAlwaysOnPackage(String, boolean, List<String>)}; previous settings from calling * that function will be replaced and saved with the always-on state. * - * @param lockdown whether to prevent all traffic outside of a VPN. + * @param lockdown whether to prevent all traffic outside of the VPN. */ public synchronized void setLockdown(boolean lockdown) { enforceControlPermissionOrInternalCaller(); @@ -969,15 +1006,21 @@ public class Vpn { // Allow VpnManager app to temporarily run background services to handle this error. // If an app requires anything beyond this grace period, they MUST either declare // themselves as a foreground service, or schedule a job/workitem. - DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal(); - idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName, - VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN, - "VpnManager event"); + final long token = Binder.clearCallingIdentity(); try { - return mUserIdContext.startService(intent) != null; - } catch (RuntimeException e) { - Log.e(TAG, "Service of VpnManager app " + intent + " failed to start", e); - return false; + final DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal(); + idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName, + VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN, + "VpnManager event"); + + try { + return mUserIdContext.startService(intent) != null; + } catch (RuntimeException e) { + Log.e(TAG, "Service of VpnManager app " + intent + " failed to start", e); + return false; + } + } finally { + Binder.restoreCallingIdentity(token); } } @@ -1102,6 +1145,7 @@ public class Vpn { mAlwaysOn = false; } + final boolean oldLockdownState = mLockdown; mLockdown = (mAlwaysOn && lockdown); mLockdownAllowlist = (mLockdown && lockdownAllowlist != null) ? Collections.unmodifiableList(new ArrayList<>(lockdownAllowlist)) @@ -1112,6 +1156,13 @@ public class Vpn { if (isCurrentPreparedPackage(packageName)) { updateAlwaysOnNotification(mNetworkInfo.getDetailedState()); setVpnForcedLocked(mLockdown); + + // Lockdown forces the VPN to be non-bypassable (see #agentConnect) because it makes + // no sense for a VPN to be bypassable when connected but not when not connected. + // As such, changes in lockdown need to restart the agent. + if (mNetworkAgent != null && oldLockdownState != mLockdown) { + startNewNetworkAgent(mNetworkAgent, "Lockdown mode changed"); + } } else { // Prepare this app. The notification will update as a side-effect of updateState(). // It also calls setVpnForcedLocked(). @@ -1349,7 +1400,8 @@ public class Vpn { // We can't just check that packageName matches mPackage, because if the app was uninstalled // and reinstalled it will no longer be prepared. Similarly if there is a shared UID, the // calling package may not be the same as the prepared package. Check both UID and package. - return getAppUid(packageName, mUserId) == mOwnerUID && mPackage.equals(packageName); + return getAppUid(mContext, packageName, mUserId) == mOwnerUID + && mPackage.equals(packageName); } /** Prepare the VPN for the given package. Does not perform permission checks. */ @@ -1390,7 +1442,7 @@ public class Vpn { Log.i(TAG, "Switched from " + mPackage + " to " + newPackage); mPackage = newPackage; - mOwnerUID = getAppUid(newPackage, mUserId); + mOwnerUID = getAppUid(mContext, newPackage, mUserId); mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage); try { mNms.allowProtect(mOwnerUID); @@ -1411,7 +1463,7 @@ public class Vpn { // Check if the caller is authorized. enforceControlPermissionOrInternalCaller(); - final int uid = getAppUid(packageName, mUserId); + final int uid = getAppUid(mContext, packageName, mUserId); if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) { // Authorization for nonexistent packages (or fake ones) can't be updated. return false; @@ -1491,11 +1543,11 @@ public class Vpn { || isVpnServicePreConsented(context, packageName); } - private int getAppUid(final String app, final int userId) { + private static int getAppUid(final Context context, final String app, final int userId) { if (VpnConfig.LEGACY_VPN.equals(app)) { return Process.myUid(); } - PackageManager pm = mContext.getPackageManager(); + PackageManager pm = context.getPackageManager(); final long token = Binder.clearCallingIdentity(); try { return pm.getPackageUidAsUser(app, userId); @@ -1624,6 +1676,10 @@ public class Vpn { */ private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) { // NetworkAgentConfig cannot be updated without registering a new NetworkAgent. + // Strictly speaking, bypassability is affected by lockdown and therefore it's possible + // it doesn't actually change even if mConfig.allowBypass changed. It might be theoretically + // possible to do handover in this case, but this is far from obvious to VPN authors and + // it's simpler if the rule is just "can't update in place if you change allow bypass". if (oldConfig.allowBypass != mConfig.allowBypass) { Log.i(TAG, "Handover not possible due to changes to allowBypass"); return false; @@ -1665,10 +1721,11 @@ public class Vpn { mLegacyState = LegacyVpnInfo.STATE_CONNECTING; updateState(DetailedState.CONNECTING, "agentConnect"); + final boolean bypassable = mConfig.allowBypass && !mLockdown; final NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig.Builder() .setLegacyType(ConnectivityManager.TYPE_VPN) .setLegacyTypeName("VPN") - .setBypassableVpn(mConfig.allowBypass && !mLockdown) + .setBypassableVpn(bypassable) .setVpnRequiresValidation(mConfig.requiresInternetValidation) .setLocalRoutesExcludedForVpn(mConfig.excludeLocalRoutes) .build(); @@ -1682,7 +1739,7 @@ public class Vpn { capsBuilder.setTransportInfo(new VpnTransportInfo( getActiveVpnType(), mConfig.session, - mConfig.allowBypass, + bypassable, expensive)); // Only apps targeting Q and above can explicitly declare themselves as metered. @@ -1713,6 +1770,10 @@ public class Vpn { Binder.restoreCallingIdentity(token); } updateState(DetailedState.CONNECTED, "agentConnect"); + if (isIkev2VpnRunner()) { + final IkeSessionWrapper session = ((IkeV2VpnRunner) mVpnRunner).mSession; + if (null != session) session.setUnderpinnedNetwork(mNetworkAgent.getNetwork()); + } } private static boolean areLongLivedTcpConnectionsExpensive(@NonNull VpnRunner runner) { @@ -1907,7 +1968,7 @@ public class Vpn { private SortedSet<Integer> getAppsUids(List<String> packageNames, int userId) { SortedSet<Integer> uids = new TreeSet<>(); for (String app : packageNames) { - int uid = getAppUid(app, userId); + int uid = getAppUid(mContext, app, userId); if (uid != -1) uids.add(uid); // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from // ConnectivityServiceTest. @@ -3226,7 +3287,6 @@ public class Vpn { prepareStatusIntent(); } agentConnect(this::onValidationStatus); - mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork()); return; // Link properties are already sent. } else { // Underlying networks also set in agentConnect() @@ -3343,7 +3403,6 @@ public class Vpn { if (!removedAddrs.isEmpty()) { startNewNetworkAgent( mNetworkAgent, "MTU too low for IPv6; restarting network agent"); - mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork()); for (LinkAddress removed : removedAddrs) { mTunnelIface.removeAddress( @@ -3391,6 +3450,7 @@ public class Vpn { * consistency of the Ikev2VpnRunner fields. */ public void onDefaultNetworkChanged(@NonNull Network network) { + mEventChanges.log("[UnderlyingNW] Default network changed to " + network); Log.d(TAG, "onDefaultNetworkChanged: " + network); // If there is a new default network brought up, cancel the retry task to prevent @@ -3621,13 +3681,14 @@ public class Vpn { final VpnTransportInfo info = new VpnTransportInfo( getActiveVpnType(), mConfig.session, - mConfig.allowBypass, + mConfig.allowBypass && !mLockdown, areLongLivedTcpConnectionsExpensive(keepaliveDelaySec)); final boolean ncUpdateRequired = !info.equals(mNetworkCapabilities.getTransportInfo()); if (ncUpdateRequired) { mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) .setTransportInfo(info) .build(); + mEventChanges.log("[VPNRunner] Update agent caps " + mNetworkCapabilities); doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities); } } @@ -3664,6 +3725,7 @@ public class Vpn { private void startIkeSession(@NonNull Network underlyingNetwork) { Log.d(TAG, "Start new IKE session on network " + underlyingNetwork); + mEventChanges.log("[IKE] Start IKE session over " + underlyingNetwork); try { // Clear mInterface to prevent Ikev2VpnRunner being cleared when @@ -3709,13 +3771,20 @@ public class Vpn { } } - private void scheduleRetryNewIkeSession() { + /** + * Schedule starting an IKE session. + * @param delayMs the delay after which to try starting the session. This should be + * RETRY_DELAY_AUTO_BACKOFF for automatic retries with backoff. + */ + private void scheduleStartIkeSession(final long delayMs) { 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."); + final long retryDelayMs = RETRY_DELAY_AUTO_BACKOFF != delayMs + ? delayMs + : mDeps.getNextRetryDelayMs(mRetryCount++); + Log.d(TAG, "Retry new IKE session after " + retryDelayMs + " milliseconds."); // If the default network is lost during the retry delay, the mActiveNetwork will be // null, and the new IKE session won't be established until there is a new default // network bringing up. @@ -3726,7 +3795,7 @@ public class Vpn { // Reset mScheduledHandleRetryIkeSessionFuture since it's already run on // executor thread. mScheduledHandleRetryIkeSessionFuture = null; - }, retryDelay, TimeUnit.SECONDS); + }, retryDelayMs, TimeUnit.MILLISECONDS); } /** Called when the NetworkCapabilities of underlying network is changed */ @@ -3735,20 +3804,26 @@ public class Vpn { + mUnderlyingNetworkCapabilities + " to " + nc); final NetworkCapabilities oldNc = mUnderlyingNetworkCapabilities; mUnderlyingNetworkCapabilities = nc; - if (oldNc == null) { - // A new default network is available. - startOrMigrateIkeSession(mActiveNetwork); - } else if (!nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) { - // Renew carrierConfig values. - maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork); + if (oldNc == null || !nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) { + // A new default network is available, or the subscription has changed. + // Try to migrate the session, or failing that, start a new one. + scheduleStartIkeSession(IKE_DELAY_ON_NC_LP_CHANGE_MS); } } /** Called when the LinkProperties of underlying network is changed */ public void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp) { - mEventChanges.log("[UnderlyingNW] Lp changed from " - + mUnderlyingLinkProperties + " to " + lp); + final LinkProperties oldLp = mUnderlyingLinkProperties; + mEventChanges.log("[UnderlyingNW] Lp changed from " + oldLp + " to " + lp); mUnderlyingLinkProperties = lp; + if (oldLp == null || !LinkPropertiesUtils.isIdenticalAllLinkAddresses(oldLp, lp)) { + // If some of the link addresses changed, the IKE session may need to be migrated + // or restarted, for example if the available IP families have changed or if the + // source address used has gone away. See IkeConnectionController#onNetworkSetByUser + // and IkeConnectionController#selectAndSetRemoteAddress for where this ends up + // re-evaluating the session. + scheduleStartIkeSession(IKE_DELAY_ON_NC_LP_CHANGE_MS); + } } class VpnConnectivityDiagnosticsCallback @@ -3778,6 +3853,7 @@ public class Vpn { } public void onValidationStatus(int status) { + mEventChanges.log("[Validation] validation status " + status); if (status == NetworkAgent.VALIDATION_STATUS_VALID) { // No data stall now. Reset it. mExecutor.execute(() -> { @@ -3818,6 +3894,7 @@ public class Vpn { * consistency of the Ikev2VpnRunner fields. */ public void onDefaultNetworkLost(@NonNull Network network) { + mEventChanges.log("[UnderlyingNW] Network lost " + network); // If the default network is torn down, there is no need to call // startOrMigrateIkeSession() since it will always check if there is an active network // can be used or not. @@ -3936,6 +4013,8 @@ public class Vpn { * consistency of the Ikev2VpnRunner fields. */ public void onSessionLost(int token, @Nullable Exception exception) { + mEventChanges.log("[IKE] Session lost on network " + mActiveNetwork + + (null == exception ? "" : " reason " + exception.getMessage())); Log.d(TAG, "onSessionLost() called for token " + token); if (!isActiveToken(token)) { @@ -4022,7 +4101,7 @@ public class Vpn { markFailedAndDisconnect(exception); return; } else { - scheduleRetryNewIkeSession(); + scheduleStartIkeSession(RETRY_DELAY_AUTO_BACKOFF); } // Close all obsolete state, but keep VPN alive incase a usable network comes up. @@ -4092,6 +4171,7 @@ public class Vpn { * consistency of the Ikev2VpnRunner fields. */ private void disconnectVpnRunner() { + mEventChanges.log("[VPNRunner] Disconnect runner, underlying network" + mActiveNetwork); mActiveNetwork = null; mUnderlyingNetworkCapabilities = null; mUnderlyingLinkProperties = null; @@ -4458,10 +4538,7 @@ public class Vpn { } private void verifyCallingUidAndPackage(String packageName) { - final int callingUid = Binder.getCallingUid(); - if (getAppUid(packageName, mUserId) != callingUid) { - throw new SecurityException(packageName + " does not belong to uid " + callingUid); - } + mDeps.verifyCallingUidAndPackage(mContext, packageName, mUserId); } @VisibleForTesting diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java index 73131a1dc220..06dd5006188a 100644 --- a/services/core/java/com/android/server/display/PersistentDataStore.java +++ b/services/core/java/com/android/server/display/PersistentDataStore.java @@ -300,8 +300,11 @@ final class PersistentDataStore { } public boolean setBrightness(DisplayDevice displayDevice, float brightness) { + if (displayDevice == null || !displayDevice.hasStableUniqueId()) { + return false; + } final String displayDeviceUniqueId = displayDevice.getUniqueId(); - if (!displayDevice.hasStableUniqueId() || displayDeviceUniqueId == null) { + if (displayDeviceUniqueId == null) { return false; } final DisplayState state = getDisplayState(displayDeviceUniqueId, true); diff --git a/services/core/java/com/android/server/infra/OWNERS b/services/core/java/com/android/server/infra/OWNERS index 0466d8a88053..4fea05d295b6 100644 --- a/services/core/java/com/android/server/infra/OWNERS +++ b/services/core/java/com/android/server/infra/OWNERS @@ -1,3 +1,3 @@ # Bug component: 655446 -include /core/java/android/service/cloudsearch/OWNERS +srazdan@google.com diff --git a/services/core/java/com/android/server/inputmethod/OWNERS b/services/core/java/com/android/server/inputmethod/OWNERS index 00cd700541c0..6e5eb5631112 100644 --- a/services/core/java/com/android/server/inputmethod/OWNERS +++ b/services/core/java/com/android/server/inputmethod/OWNERS @@ -1,8 +1,8 @@ set noparent -ogunwale@google.com +roosa@google.com yukawa@google.com tarandeep@google.com -lumark@google.com -roosa@google.com -wilsonwu@google.com + +ogunwale@google.com #{LAST_RESORT_SUGGESTION} +jjaggi@google.com #{LAST_RESORT_SUGGESTION} diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java index 1235352b0590..f0aff2a503b0 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -300,6 +300,7 @@ public class LocationProviderManager extends public void deliverOnFlushComplete(int requestCode) throws PendingIntent.CanceledException { BroadcastOptions options = BroadcastOptions.makeBasic(); options.setDontSendToRestrictedApps(true); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_FLUSH_COMPLETE, requestCode), null, null, null, options.toBundle()); diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 65bd3f12a61a..0f13c2ca8bd8 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -108,7 +108,7 @@ public class PreferencesHelper implements RankingConfig { @VisibleForTesting static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000; @VisibleForTesting - static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 50000; + static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 6000; private static final int NOTIFICATION_PREFERENCES_PULL_LIMIT = 1000; private static final int NOTIFICATION_CHANNEL_PULL_LIMIT = 2000; diff --git a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java index b4bcd5b3308c..5de15595df6d 100644 --- a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java +++ b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java @@ -61,7 +61,7 @@ public class DynamicCodeLoggingService extends JobService { private static final String AVC_PREFIX = "type=" + AUDIT_AVC + " "; private static final Pattern EXECUTE_NATIVE_AUDIT_PATTERN = - Pattern.compile(".*\\bavc: granted \\{ execute(?:_no_trans|) \\} .*" + Pattern.compile(".*\\bavc: +granted +\\{ execute(?:_no_trans|) \\} .*" + "\\bpath=(?:\"([^\" ]*)\"|([0-9A-F]+)) .*" + "\\bscontext=u:r:untrusted_app(?:_25|_27)?:.*" + "\\btcontext=u:object_r:app_data_file:.*" diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 0de44bc5d6b3..6a40a3efd30f 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -94,6 +94,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.ApplicationPackageManager; +import android.app.BroadcastOptions; import android.app.backup.IBackupManager; import android.content.ContentResolver; import android.content.Context; @@ -641,7 +642,10 @@ final class InstallPackageHelper { fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageManager.installStatusToPublicStatus(returnCode)); try { - target.sendIntent(context, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + target.sendIntent(context, 0, fillIn, null /* onFinished*/, null /* handler */, + null /* requiredPermission */, options.toBundle()); } catch (IntentSender.SendIntentException ignored) { } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index bb23d89d218f..02cf4336b277 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -27,6 +27,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.BroadcastOptions; import android.app.Notification; import android.app.NotificationManager; import android.app.PackageDeleteObserver; @@ -1360,7 +1361,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements PackageInstaller.STATUS_PENDING_USER_ACTION); fillIn.putExtra(Intent.EXTRA_INTENT, intent); try { - mTarget.sendIntent(mContext, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (SendIntentException ignored) { } } @@ -1385,7 +1389,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements PackageManager.deleteStatusToString(returnCode, msg)); fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode); try { - mTarget.sendIntent(mContext, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (SendIntentException ignored) { } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 7c2e3ea426b4..1823de8fcf66 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -54,6 +54,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.WorkerThread; import android.app.AppOpsManager; +import android.app.BroadcastOptions; import android.app.Notification; import android.app.NotificationManager; import android.app.admin.DevicePolicyEventLogger; @@ -4274,7 +4275,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION); fillIn.putExtra(Intent.EXTRA_INTENT, intent); try { - target.sendIntent(context, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + target.sendIntent(context, 0, fillIn, null /* onFinished */, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (IntentSender.SendIntentException ignored) { } } @@ -4315,7 +4319,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } try { - target.sendIntent(context, 0, fillIn, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + target.sendIntent(context, 0, fillIn, null /* onFinished */, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (IntentSender.SendIntentException ignored) { } } @@ -4349,7 +4356,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready"); } try { - target.sendIntent(context, 0, intent, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + target.sendIntent(context, 0, intent, null /* onFinished */, + null /* handler */, null /* requiredPermission */, options.toBundle()); } catch (IntentSender.SendIntentException ignored) { } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 8d2714cacf10..47860373156b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -53,6 +53,7 @@ import android.annotation.WorkerThread; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.ApplicationPackageManager; +import android.app.BroadcastOptions; import android.app.IActivityManager; import android.app.admin.IDevicePolicyManager; import android.app.admin.SecurityLog; @@ -4798,7 +4799,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService } if (pi != null) { try { - pi.sendIntent(null, success ? 1 : 0, null, null, null); + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); + pi.sendIntent(null, success ? 1 : 0, null /* intent */, + null /* onFinished*/, null /* handler */, + null /* requiredPermission */, options.toBundle()); } catch (SendIntentException e) { Slog.w(TAG, e); } diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java index 7ce7f7ebf6cc..810fa5f1e4b3 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java @@ -247,6 +247,9 @@ public class ParsingPackageUtils { private static final String MAX_NUM_COMPONENTS_ERR_MSG = "Total number of components has exceeded the maximum number: " + MAX_NUM_COMPONENTS; + /** The maximum permission name length. */ + private static final int MAX_PERMISSION_NAME_LENGTH = 512; + @IntDef(flag = true, prefix = { "PARSE_" }, value = { PARSE_CHATTY, PARSE_COLLECT_CERTIFICATES, @@ -1275,6 +1278,11 @@ public class ParsingPackageUtils { // that may change. String name = sa.getNonResourceString( R.styleable.AndroidManifestUsesPermission_name); + if (TextUtils.length(name) > MAX_PERMISSION_NAME_LENGTH) { + return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "The name in the <uses-permission> is greater than " + + MAX_PERMISSION_NAME_LENGTH); + } int maxSdkVersion = 0; TypedValue val = sa.peekValue( diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java index 2d3ede02a6a4..f586126196dd 100644 --- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java +++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java @@ -70,12 +70,14 @@ final class RemoteProvisioningRegistration extends IRegistration.Stub { Log.i(TAG, "Operation cancelled for client " + mCallback.hashCode()); wrapCallback(mCallback::onCancel); } else if (e instanceof RkpProxyException) { - Log.e(TAG, "RKP error fetching key for client " + mCallback.hashCode(), e); + Log.e(TAG, "RKP error fetching key for client " + mCallback.hashCode() + ": " + + e.getMessage()); RkpProxyException rkpException = (RkpProxyException) e; wrapCallback(() -> mCallback.onError(toGetKeyError(rkpException), e.getMessage())); } else { - Log.e(TAG, "Error fetching key for client " + mCallback.hashCode(), e); + Log.e(TAG, "Unknown error fetching key for client " + mCallback.hashCode() + ": " + + e.getMessage()); wrapCallback(() -> mCallback.onError(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN, e.getMessage())); } diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java index fd6c9743cb6b..b160af6a3e11 100644 --- a/services/core/java/com/android/server/wm/AppTaskImpl.java +++ b/services/core/java/com/android/server/wm/AppTaskImpl.java @@ -98,7 +98,7 @@ class AppTaskImpl extends IAppTask.Stub { throw new IllegalArgumentException("Unable to find task ID " + mTaskId); } return mService.getRecentTasks().createRecentTaskInfo(task, - false /* stripExtras */); + false /* stripExtras */, true /* getTasksAllowed */); } finally { Binder.restoreCallingIdentity(origId); } diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index 4860762a5f7f..1fc061b2ca78 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -976,7 +976,7 @@ class RecentTasks { continue; } - res.add(createRecentTaskInfo(task, true /* stripExtras */)); + res.add(createRecentTaskInfo(task, true /* stripExtras */, getTasksAllowed)); } return res; } @@ -1895,7 +1895,8 @@ class RecentTasks { /** * Creates a new RecentTaskInfo from a Task. */ - ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras) { + ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras, + boolean getTasksAllowed) { final ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo(); // If the recent Task is detached, we consider it will be re-attached to the default // TaskDisplayArea because we currently only support recent overview in the default TDA. @@ -1907,6 +1908,9 @@ class RecentTasks { rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID; rti.persistentId = rti.taskId; rti.lastSnapshotData.set(tr.mLastTaskSnapshotData); + if (!getTasksAllowed) { + Task.trimIneffectiveInfo(tr, rti); + } // Fill in organized child task info for the task created by organizer. if (tr.mCreatedByOrganizer) { diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java index 33f019e0c9fb..4e339f1867ae 100644 --- a/services/core/java/com/android/server/wm/RunningTasks.java +++ b/services/core/java/com/android/server/wm/RunningTasks.java @@ -177,6 +177,10 @@ class RunningTasks { } // Fill in some deprecated values rti.id = rti.taskId; + + if (!mAllowed) { + Task.trimIneffectiveInfo(task, rti); + } return rti; } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 25957f15bd20..e0e5ba8c6545 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3471,6 +3471,54 @@ class Task extends TaskFragment { info.isSleeping = shouldSleepActivities(); } + /** + * Removes the activity info if the activity belongs to a different uid, which is + * different from the app that hosts the task. + */ + static void trimIneffectiveInfo(Task task, TaskInfo info) { + final ActivityRecord baseActivity = task.getActivity(r -> !r.finishing, + false /* traverseTopToBottom */); + final int baseActivityUid = + baseActivity != null ? baseActivity.getUid() : task.effectiveUid; + + if (info.topActivityInfo != null + && task.effectiveUid != info.topActivityInfo.applicationInfo.uid) { + // Making a copy to prevent eliminating the info in the original ActivityRecord. + info.topActivityInfo = new ActivityInfo(info.topActivityInfo); + info.topActivityInfo.applicationInfo = + new ApplicationInfo(info.topActivityInfo.applicationInfo); + + // Strip the sensitive info. + info.topActivity = new ComponentName("", ""); + info.topActivityInfo.packageName = ""; + info.topActivityInfo.taskAffinity = ""; + info.topActivityInfo.processName = ""; + info.topActivityInfo.name = ""; + info.topActivityInfo.parentActivityName = ""; + info.topActivityInfo.targetActivity = ""; + info.topActivityInfo.splitName = ""; + info.topActivityInfo.applicationInfo.className = ""; + info.topActivityInfo.applicationInfo.credentialProtectedDataDir = ""; + info.topActivityInfo.applicationInfo.dataDir = ""; + info.topActivityInfo.applicationInfo.deviceProtectedDataDir = ""; + info.topActivityInfo.applicationInfo.manageSpaceActivityName = ""; + info.topActivityInfo.applicationInfo.nativeLibraryDir = ""; + info.topActivityInfo.applicationInfo.nativeLibraryRootDir = ""; + info.topActivityInfo.applicationInfo.processName = ""; + info.topActivityInfo.applicationInfo.publicSourceDir = ""; + info.topActivityInfo.applicationInfo.scanPublicSourceDir = ""; + info.topActivityInfo.applicationInfo.scanSourceDir = ""; + info.topActivityInfo.applicationInfo.sourceDir = ""; + info.topActivityInfo.applicationInfo.taskAffinity = ""; + info.topActivityInfo.applicationInfo.name = ""; + info.topActivityInfo.applicationInfo.packageName = ""; + } + + if (task.effectiveUid != baseActivityUid) { + info.baseActivity = new ComponentName("", ""); + } + } + @Nullable PictureInPictureParams getPictureInPictureParams() { final Task topTask = getTopMostTask(); if (topTask == null) return null; diff --git a/services/core/java/com/android/server/wm/TaskFpsCallbackController.java b/services/core/java/com/android/server/wm/TaskFpsCallbackController.java index c09962843890..8c798759c890 100644 --- a/services/core/java/com/android/server/wm/TaskFpsCallbackController.java +++ b/services/core/java/com/android/server/wm/TaskFpsCallbackController.java @@ -26,8 +26,8 @@ import java.util.HashMap; final class TaskFpsCallbackController { private final Context mContext; - private final HashMap<ITaskFpsCallback, Long> mTaskFpsCallbacks; - private final HashMap<ITaskFpsCallback, IBinder.DeathRecipient> mDeathRecipients; + private final HashMap<IBinder, Long> mTaskFpsCallbacks; + private final HashMap<IBinder, IBinder.DeathRecipient> mDeathRecipients; TaskFpsCallbackController(Context context) { mContext = context; @@ -36,32 +36,42 @@ final class TaskFpsCallbackController { } void registerListener(int taskId, ITaskFpsCallback callback) { - if (mTaskFpsCallbacks.containsKey(callback)) { + if (callback == null) { + return; + } + + IBinder binder = callback.asBinder(); + if (mTaskFpsCallbacks.containsKey(binder)) { return; } final long nativeListener = nativeRegister(callback, taskId); - mTaskFpsCallbacks.put(callback, nativeListener); + mTaskFpsCallbacks.put(binder, nativeListener); final IBinder.DeathRecipient deathRecipient = () -> unregisterListener(callback); try { - callback.asBinder().linkToDeath(deathRecipient, 0); - mDeathRecipients.put(callback, deathRecipient); + binder.linkToDeath(deathRecipient, 0); + mDeathRecipients.put(binder, deathRecipient); } catch (RemoteException e) { // ignore } } void unregisterListener(ITaskFpsCallback callback) { - if (!mTaskFpsCallbacks.containsKey(callback)) { + if (callback == null) { + return; + } + + IBinder binder = callback.asBinder(); + if (!mTaskFpsCallbacks.containsKey(binder)) { return; } - callback.asBinder().unlinkToDeath(mDeathRecipients.get(callback), 0); - mDeathRecipients.remove(callback); + binder.unlinkToDeath(mDeathRecipients.get(binder), 0); + mDeathRecipients.remove(binder); - nativeUnregister(mTaskFpsCallbacks.get(callback)); - mTaskFpsCallbacks.remove(callback); + nativeUnregister(mTaskFpsCallbacks.get(binder)); + mTaskFpsCallbacks.remove(binder); } private static native long nativeRegister(ITaskFpsCallback callback, int taskId); diff --git a/services/tests/PackageManagerServiceTests/TEST_MAPPING b/services/tests/PackageManagerServiceTests/TEST_MAPPING index e98acb2bb6a9..5d96af9df1fb 100644 --- a/services/tests/PackageManagerServiceTests/TEST_MAPPING +++ b/services/tests/PackageManagerServiceTests/TEST_MAPPING @@ -55,23 +55,10 @@ // TODO(b/204133664) "exclude-filter": "com.android.server.pm.test.SdCardEjectionTests" }, - { - // TODO(b/272575212) - "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptDataBinaryXml" - }, - { - "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptDataTextXml" - }, - { - "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptHeaderBinaryXml" - }, - { - "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptHeaderTextXml" - }, - { + { // TODO(b/272714903) "exclude-filter": "com.android.server.pm.test.OverlayPathsUninstallSystemUpdatesTest#verify" - } + } ] } ], diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index adf694c2a88d..db6ac0b432b3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -30,6 +30,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; +import static android.os.Process.NOBODY_UID; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; @@ -1220,20 +1221,35 @@ public class RecentTasksTest extends WindowTestsBase { @Test public void testCreateRecentTaskInfo_detachedTask() { - final Task task = createTaskBuilder(".Task").setCreateActivity(true).build(); + final Task task = createTaskBuilder(".Task").build(); + final ComponentName componentName = getUniqueComponentName(); + new ActivityBuilder(mSupervisor.mService) + .setTask(task) + .setUid(NOBODY_UID) + .setComponent(componentName) + .build(); final TaskDisplayArea tda = task.getDisplayArea(); assertTrue(task.isAttached()); assertTrue(task.supportsMultiWindow()); - RecentTaskInfo info = mRecentTasks.createRecentTaskInfo(task, true); + RecentTaskInfo info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + true /* getTasksAllowed */); assertTrue(info.supportsMultiWindow); + info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + false /* getTasksAllowed */); + + assertFalse(info.topActivity.equals(componentName)); + assertFalse(info.topActivityInfo.packageName.equals(componentName.getPackageName())); + assertFalse(info.baseActivity.equals(componentName)); + // The task can be put in split screen even if it is not attached now. task.removeImmediately(); - info = mRecentTasks.createRecentTaskInfo(task, true); + info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + true /* getTasksAllowed */); assertTrue(info.supportsMultiWindow); @@ -1242,7 +1258,8 @@ public class RecentTasksTest extends WindowTestsBase { doReturn(false).when(tda).supportsNonResizableMultiWindow(); doReturn(false).when(task).isResizeable(); - info = mRecentTasks.createRecentTaskInfo(task, true); + info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + true /* getTasksAllowed */); assertFalse(info.supportsMultiWindow); @@ -1250,7 +1267,8 @@ public class RecentTasksTest extends WindowTestsBase { // the device supports it. doReturn(true).when(tda).supportsNonResizableMultiWindow(); - info = mRecentTasks.createRecentTaskInfo(task, true); + info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */, + true /* getTasksAllowed */); assertTrue(info.supportsMultiWindow); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 329849bd7682..c90b94dc64c1 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -3708,13 +3708,12 @@ public class CarrierConfigManager { * NR_SA - NR SA is unmetered for sub-6 frequencies * NR_SA_MMWAVE - NR SA is unmetered for mmwave frequencies * - * Note that this config only applies if an unmetered SubscriptionPlan is set via - * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set + * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link + * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set * via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)} * or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}. * If neither SubscriptionPlans nor an override are set, then no network types can be unmetered * regardless of the value of this config. - * TODO: remove other unmetered keys and replace with this * @hide */ public static final String KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY = @@ -3729,73 +3728,18 @@ public class CarrierConfigManager { * NR_SA - NR SA is unmetered when roaming for sub-6 frequencies * NR_SA_MMWAVE - NR SA is unmetered when roaming for mmwave frequencies * - * Note that this config only applies if an unmetered SubscriptionPlan is set via - * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set + * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link + * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set * via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)} * or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}. * If neither SubscriptionPlans nor an override are set, then no network types can be unmetered * when roaming regardless of the value of this config. - * TODO: remove KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL and replace with this * @hide */ public static final String KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY = "roaming_unmetered_network_types_string_array"; /** - * Whether NR (non-standalone) should be unmetered for all frequencies. - * If either {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL} or - * {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL} are true, then this value will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_NSA_BOOL = "unmetered_nr_nsa_bool"; - - /** - * Whether NR (non-standalone) frequencies above 6GHz (millimeter wave) should be unmetered. - * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_NSA_MMWAVE_BOOL = "unmetered_nr_nsa_mmwave_bool"; - - /** - * Whether NR (non-standalone) frequencies below 6GHz (sub6) should be unmetered. - * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_NSA_SUB6_BOOL = "unmetered_nr_nsa_sub6_bool"; - - /** - * Whether NR (non-standalone) should be unmetered when the device is roaming. - * If false, then the values for {@link #KEY_UNMETERED_NR_NSA_BOOL}, - * {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL}, {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL}, - * and unmetered {@link SubscriptionPlan} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL = - "unmetered_nr_nsa_when_roaming_bool"; - - /** - * Whether NR (standalone) should be unmetered for all frequencies. - * If either {@link #KEY_UNMETERED_NR_SA_MMWAVE_BOOL} or - * {@link #KEY_UNMETERED_NR_SA_SUB6_BOOL} are true, then this value will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_SA_BOOL = "unmetered_nr_sa_bool"; - - /** - * Whether NR (standalone) frequencies above 6GHz (millimeter wave) should be unmetered. - * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_SA_MMWAVE_BOOL = "unmetered_nr_sa_mmwave_bool"; - - /** - * Whether NR (standalone) frequencies below 6GHz (sub6) should be unmetered. - * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored. - * @hide - */ - public static final String KEY_UNMETERED_NR_SA_SUB6_BOOL = "unmetered_nr_sa_sub6_bool"; - - /** * Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable * this feature. * @hide @@ -9255,13 +9199,6 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[] { "NR_NSA", "NR_NSA_MMWAVE", "NR_SA", "NR_SA_MMWAVE"}); sDefaults.putStringArray(KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[0]); - sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_SUB6_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_SA_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_SA_MMWAVE_BOOL, false); - sDefaults.putBoolean(KEY_UNMETERED_NR_SA_SUB6_BOOL, false); sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false); sDefaults.putBoolean(KEY_SHOW_WIFI_CALLING_ICON_IN_STATUS_BAR_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, false); diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index d590ce22e9df..45c092e1fb0d 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -160,6 +160,10 @@ public class SubscriptionManager { private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY = "cache_key.telephony.subscription_manager_service"; + /** The temporarily cache key to indicate whether subscription manager service is enabled. */ + private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY = + "cache_key.telephony.subscription_manager_service_enabled"; + /** @hide */ public static final String GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME = "getSimSpecificSettings"; @@ -317,6 +321,12 @@ public class SubscriptionManager { CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY, INVALID_PHONE_INDEX); + //TODO: Removed before U AOSP public release. + private static VoidPropertyInvalidatedCache<Boolean> sIsSubscriptionManagerServiceEnabled = + new VoidPropertyInvalidatedCache<>(ISub::isSubscriptionManagerServiceEnabled, + CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY, + false); + /** * Generates a content {@link Uri} used to receive updates on simInfo change * on the given subscriptionId @@ -1335,8 +1345,6 @@ public class SubscriptionManager { private final Context mContext; - private static boolean sIsSubscriptionManagerServiceEnabled = false; - // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing // the Context and subId. private static final Map<Pair<Context, Integer>, Resources> sResourcesCache = @@ -1422,9 +1430,6 @@ public class SubscriptionManager { public SubscriptionManager(Context context) { if (DBG) logd("SubscriptionManager created"); mContext = context; - - sIsSubscriptionManagerServiceEnabled = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_using_subscription_manager_service); } /** @@ -1433,8 +1438,9 @@ public class SubscriptionManager { * * @hide */ + //TODO: Removed before U AOSP public release. public static boolean isSubscriptionManagerServiceEnabled() { - return sIsSubscriptionManagerServiceEnabled; + return sIsSubscriptionManagerServiceEnabled.query(null); } private NetworkPolicyManager getNetworkPolicyManager() { @@ -3947,6 +3953,13 @@ public class SubscriptionManager { PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY); } + /** @hide */ + //TODO: Removed before U AOSP public release. + public static void invalidateSubscriptionManagerServiceEnabledCaches() { + PropertyInvalidatedCache.invalidateCache( + CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY); + } + /** * Allows a test process to disable client-side caching operations. * @@ -3968,6 +3981,8 @@ public class SubscriptionManager { sGetSlotIndexCache.disableLocal(); sGetSubIdCache.disableLocal(); sGetPhoneIdCache.disableLocal(); + + sIsSubscriptionManagerServiceEnabled.disableLocal(); } /** @@ -3990,6 +4005,8 @@ public class SubscriptionManager { sGetSlotIndexCache.clear(); sGetSubIdCache.clear(); sGetPhoneIdCache.clear(); + + sIsSubscriptionManagerServiceEnabled.clear(); } /** diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index fd5ec258d697..fa60031f2a66 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -311,6 +311,31 @@ public class TelephonyManager { public static final int SRVCC_STATE_HANDOVER_CANCELED = 3; /** + * Convert srvcc handover state to string. + * + * @param state The srvcc handover state. + * @return The srvcc handover state in string format. + * + * @hide + */ + public static @NonNull String srvccStateToString(int state) { + switch (state) { + case TelephonyManager.SRVCC_STATE_HANDOVER_NONE: + return "NONE"; + case TelephonyManager.SRVCC_STATE_HANDOVER_STARTED: + return "STARTED"; + case TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED: + return "COMPLETED"; + case TelephonyManager.SRVCC_STATE_HANDOVER_FAILED: + return "FAILED"; + case TelephonyManager.SRVCC_STATE_HANDOVER_CANCELED: + return "CANCELED"; + default: + return "UNKNOWN(" + state + ")"; + } + } + + /** * A UICC card identifier used if the device does not support the operation. * For example, {@link #getCardIdForDefaultEuicc()} returns this value if the device has no * eUICC, or the eUICC cannot be read. diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index 25a714a4bb81..defa046da503 100644 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -356,4 +356,11 @@ interface ISub { * @hide */ List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(in UserHandle userHandle); + + /** + * @return {@code true} if using SubscriptionManagerService instead of + * SubscriptionController. + */ + //TODO: Removed before U AOSP public release. + boolean isSubscriptionManagerServiceEnabled(); } diff --git a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java index 5430dee5ca31..afa4ff80b6e3 100644 --- a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java +++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java @@ -84,7 +84,7 @@ public final class DynamicCodeLoggerIntegrationTests { // avoid flakiness we run these tests multiple times, allowing progressively longer between // code loading and checking the logs on each try.) private static final int AUDIT_LOG_RETRIES = 10; - private static final int RETRY_DELAY_MS = 2_000; + private static final int RETRY_DELAY_MS = 500; private static Context sContext; private static int sMyUid; @@ -245,7 +245,7 @@ public final class DynamicCodeLoggerIntegrationTests { "/DynamicCodeLoggerNativeExecutable", privateCopyFile); EventLog.writeEvent(EventLog.getTagCode("auditd"), - "type=1400 avc: granted { execute_no_trans } " + "type=1400 avc: granted { execute_no_trans } " + "path=\"" + privateCopyFile + "\" " + "scontext=u:r:untrusted_app: " + "tcontext=u:object_r:app_data_file: " diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp index de9bbb6ef9fa..a92a6ae5a7a4 100644 --- a/tests/Input/Android.bp +++ b/tests/Input/Android.bp @@ -21,7 +21,7 @@ android_test { "services.core.unboosted", "testables", "truth-prebuilt", - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", ], test_suites: ["device-tests"], } diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt index 1d65cc35c3bc..8025406499d8 100644 --- a/tests/Input/src/com/android/test/input/AnrTest.kt +++ b/tests/Input/src/com/android/test/input/AnrTest.kt @@ -27,14 +27,15 @@ import android.os.IInputConstants.UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLI import android.os.SystemClock import android.provider.Settings import android.provider.Settings.Global.HIDE_ERROR_DIALOGS -import android.support.test.uiautomator.By -import android.support.test.uiautomator.UiDevice -import android.support.test.uiautomator.UiObject2 -import android.support.test.uiautomator.Until import android.testing.PollingCheck import android.view.InputDevice import android.view.MotionEvent +import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiDevice +import androidx.test.uiautomator.UiObject2 +import androidx.test.uiautomator.Until + import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/tests/OdmApps/Android.bp b/tests/OdmApps/Android.bp index 5f03aa27e6df..a5c6d6513f50 100644 --- a/tests/OdmApps/Android.bp +++ b/tests/OdmApps/Android.bp @@ -28,5 +28,6 @@ java_test_host { test_suites: ["device-tests"], data: [ ":TestOdmApp", + ":TestOdmPrivApp", ], } diff --git a/tests/WindowAnimationJank/Android.bp b/tests/WindowAnimationJank/Android.bp index ed86aa5f90ea..8542f885d645 100644 --- a/tests/WindowAnimationJank/Android.bp +++ b/tests/WindowAnimationJank/Android.bp @@ -25,7 +25,7 @@ android_test { name: "WindowAnimationJank", srcs: ["src/**/*.java"], static_libs: [ - "ub-uiautomator", + "androidx.test.uiautomator_uiautomator", "androidx.test.janktesthelper", "junit", ], diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java b/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java index 25314644ca7e..48a359c4d0c6 100644 --- a/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java +++ b/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java @@ -18,11 +18,12 @@ import android.app.UiAutomation; import android.content.ComponentName; import android.content.Intent; import android.os.SystemClock; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; -import android.support.test.uiautomator.Until; + +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; +import androidx.test.uiautomator.Until; /** * Set of helpers to manipulate test activities. diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java index a8ace162c4d0..cb7c5112cba7 100644 --- a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java +++ b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java @@ -16,9 +16,8 @@ package android.windowanimationjank; -import android.support.test.uiautomator.UiDevice; - import androidx.test.jank.JankTestBase; +import androidx.test.uiautomator.UiDevice; /** * This adds additional system level jank monitor and its result is merged with primary monitor |