diff options
62 files changed, 723 insertions, 251 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/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/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/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/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/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/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 7e48f68dcefc..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( @@ -3622,7 +3681,7 @@ 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) { @@ -3712,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. @@ -3729,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 */ @@ -3738,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 @@ -4029,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. @@ -4466,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/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/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/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/SharedLibraryLoadingTest/AndroidTest.xml b/tests/SharedLibraryLoadingTest/AndroidTest.xml index 947453d07bd9..ad0584724fdc 100644 --- a/tests/SharedLibraryLoadingTest/AndroidTest.xml +++ b/tests/SharedLibraryLoadingTest/AndroidTest.xml @@ -22,7 +22,6 @@ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" /> <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> - <option name="cleanup" value="false" /> <option name="remount-system" value="true" /> <option name="push" value="SharedLibraryLoadingTests_StandardSharedLibrary.apk->/product/app/SharedLibraryLoadingTests_StandardSharedLibrary.apk" /> 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 |