From 2c34dcd95606389ba8b9f9f88de244d640312db1 Mon Sep 17 00:00:00 2001 From: Jacob Hobbie <@google.com> Date: Wed, 24 Nov 2021 01:02:45 +0000 Subject: [PATCH] Adding client side logging for receivers. Adding logging so that we can log wtfs and know where they are coming from without the trace being swallowed by the binder. This will help track down locations where receivers are being registered for non-system broadcasts but aren't specifying the necessary flags. Bug: 161145287 Bug: 207378016 Test: Just adding logging that will be deleted Change-Id: Ib20c4015caf76ae946bbf2a7fc434777856c18fe --- core/java/android/app/ContextImpl.java | 4 ++ core/java/android/app/WtfException.java | 66 +++++++++++++++++++ .../server/am/ActivityManagerService.java | 19 ++++-- 3 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 core/java/android/app/WtfException.java diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 756833a012a48..c5ea2bc11fd1b 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1786,6 +1786,7 @@ class ContextImpl extends Context { && ((flags & Context.RECEIVER_NOT_EXPORTED) == 0)) { flags = flags | Context.RECEIVER_EXPORTED; } + final Intent intent = ActivityManager.getService().registerReceiverWithFeature( mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, userId, @@ -1800,6 +1801,9 @@ class ContextImpl extends Context { return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (WtfException e) { + Log.wtf(TAG, e.getMessage()); + return null; } } diff --git a/core/java/android/app/WtfException.java b/core/java/android/app/WtfException.java new file mode 100644 index 0000000000000..ba8dbefad160e --- /dev/null +++ b/core/java/android/app/WtfException.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Exception meant to be thrown instead of calling Log.wtf() such that server side code can + * throw this exception, and it will carry across the binder to do client side logging. + * {@hide} + */ +public final class WtfException extends RuntimeException implements Parcelable { + public static final @android.annotation.NonNull + Creator CREATOR = new Creator() { + @Override + public WtfException createFromParcel(Parcel source) { + return new WtfException(source.readString8()); + } + + @Override + public WtfException[] newArray(int size) { + return new WtfException[size]; + } + }; + + public WtfException(@android.annotation.NonNull String message) { + super(message); + } + + /** {@hide} */ + public static Throwable readFromParcel(Parcel in) { + final String msg = in.readString8(); + return new WtfException(msg); + } + + /** {@hide} */ + public static void writeToParcel(Parcel out, Throwable t) { + out.writeString8(t.getMessage()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@android.annotation.NonNull Parcel dest, int flags) { + dest.writeString8(getMessage()); + } +} + diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 02a16fc08c55e..d92fda6a05e30 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -188,6 +188,7 @@ import android.app.ProfilerInfo; import android.app.PropertyInvalidatedCache; import android.app.SyncNotedAppOp; import android.app.WaitResult; +import android.app.WtfException; import android.app.backup.BackupManager.OperationType; import android.app.backup.IBackupManager; import android.app.compat.CompatChanges; @@ -12615,6 +12616,7 @@ public class ActivityManagerService extends IActivityManager.Stub int callingUid; int callingPid; boolean instantApp; + boolean throwWtfException = false; synchronized(this) { if (caller != null) { callerApp = getRecordForAppLOSP(caller); @@ -12709,13 +12711,9 @@ public class ActivityManagerService extends IActivityManager.Stub + "RECEIVER_NOT_EXPORTED be specified when registering a " + "receiver"); } else { - Slog.wtf(TAG, - callerPackage + ": Targeting T+ (version " - + Build.VERSION_CODES.TIRAMISU - + " and above) requires that one of RECEIVER_EXPORTED or " - + "RECEIVER_NOT_EXPORTED be specified when registering a " - + "receiver"); + // will be removed when enforcement is required // Assume default behavior-- flag check is not enforced + throwWtfException = true; flags |= Context.RECEIVER_EXPORTED; } } else if (!requireExplicitFlagForDynamicReceivers) { @@ -12846,6 +12844,15 @@ public class ActivityManagerService extends IActivityManager.Stub } } + if (throwWtfException) { + throw new WtfException( + callerPackage + ": Targeting T+ (version " + + Build.VERSION_CODES.TIRAMISU + + " and above) requires that one of RECEIVER_EXPORTED or " + + "RECEIVER_NOT_EXPORTED be specified when registering a " + + "receiver"); + } + return sticky; } }