diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-10-11 22:52:44 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-10-11 22:52:44 +0000 |
commit | 2e2bd22cde6984bed06c905cbf3a79093153d2e6 (patch) | |
tree | 5a206197328a5d1fc9d4dcfac78388b4365be419 | |
parent | 05157e53905dbbf09dd6898f7bd7f9d4781165fc (diff) | |
parent | 9b68987df85b681f9362a3cadca6496796d23bbc (diff) | |
download | base-android-security-14.0.0_r3.tar.gz |
Merge cherrypicks of ['googleplex-android-review.googlesource.com/23918399', 'googleplex-android-review.googlesource.com/24405959', 'googleplex-android-review.googlesource.com/23987679', 'googleplex-android-review.googlesource.com/23988011', 'googleplex-android-review.googlesource.com/24029253', 'googleplex-android-review.googlesource.com/24005105', 'googleplex-android-review.googlesource.com/24575247', 'googleplex-android-review.googlesource.com/24046929', 'googleplex-android-review.googlesource.com/24339445', 'googleplex-android-review.googlesource.com/24762427', 'googleplex-android-review.googlesource.com/23623415', 'googleplex-android-review.googlesource.com/24606761', 'googleplex-android-review.googlesource.com/24182288', 'googleplex-android-review.googlesource.com/24790879', 'googleplex-android-review.googlesource.com/24058898', 'googleplex-android-review.googlesource.com/24419913', 'googleplex-android-review.googlesource.com/24555974', 'googleplex-android-review.googlesource.com/24945646', 'googleplex-android-review.googlesource.com/24998046'] into security-aosp-udc-release.android-security-14.0.0_r3
Change-Id: Ied6ee6a70346e8ab95b3057a0067f9a18c26c8f1
54 files changed, 1091 insertions, 580 deletions
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp index f41e57cc66d6..add0d8d48108 100644 --- a/cmds/idmap2/idmap2/Lookup.cpp +++ b/cmds/idmap2/idmap2/Lookup.cpp @@ -174,7 +174,7 @@ Result<Unit> Lookup(const std::vector<std::string>& args) { return Error("failed to parse config"); } - std::vector<std::unique_ptr<const ApkAssets>> apk_assets; + std::vector<AssetManager2::ApkAssetsPtr> apk_assets; std::string target_path; std::string target_package_name; for (size_t i = 0; i < idmap_paths.size(); i++) { @@ -217,24 +217,21 @@ Result<Unit> Lookup(const std::vector<std::string>& args) { apk_assets.push_back(std::move(overlay_apk)); } - // AssetManager2::SetApkAssets requires raw ApkAssets pointers, not unique_ptrs - std::vector<const ApkAssets*> raw_pointer_apk_assets; - std::transform(apk_assets.cbegin(), apk_assets.cend(), std::back_inserter(raw_pointer_apk_assets), - [](const auto& p) -> const ApkAssets* { return p.get(); }); - AssetManager2 am; - am.SetApkAssets(raw_pointer_apk_assets); - am.SetConfiguration(config); - - const Result<ResourceId> resid = ParseResReference(am, resid_str, target_package_name); - if (!resid) { - return Error(resid.GetError(), "failed to parse resource ID"); - } + { + // Make sure |apk_assets| vector outlives the asset manager as it doesn't own the assets. + AssetManager2 am(apk_assets, config); + + const Result<ResourceId> resid = ParseResReference(am, resid_str, target_package_name); + if (!resid) { + return Error(resid.GetError(), "failed to parse resource ID"); + } - const Result<std::string> value = GetValue(&am, *resid); - if (!value) { - return Error(value.GetError(), "resource 0x%08x not found", *resid); + const Result<std::string> value = GetValue(&am, *resid); + if (!value) { + return Error(value.GetError(), "resource 0x%08x not found", *resid); + } + std::cout << *value << std::endl; } - std::cout << *value << std::endl; return Unit{}; } diff --git a/cmds/idmap2/libidmap2/ResourceContainer.cpp b/cmds/idmap2/libidmap2/ResourceContainer.cpp index 0e3590486c6f..7869fbdb8cea 100644 --- a/cmds/idmap2/libidmap2/ResourceContainer.cpp +++ b/cmds/idmap2/libidmap2/ResourceContainer.cpp @@ -262,7 +262,7 @@ OverlayData CreateResourceMappingLegacy(const AssetManager2* overlay_am, } struct ResState { - std::unique_ptr<ApkAssets> apk_assets; + AssetManager2::ApkAssetsPtr apk_assets; const LoadedArsc* arsc; const LoadedPackage* package; std::unique_ptr<AssetManager2> am; @@ -284,7 +284,7 @@ struct ResState { } state.am = std::make_unique<AssetManager2>(); - if (!state.am->SetApkAssets({state.apk_assets.get()})) { + if (!state.am->SetApkAssets({state.apk_assets})) { return Error("failed to create asset manager"); } diff --git a/cmds/idmap2/tests/ResourceUtilsTests.cpp b/cmds/idmap2/tests/ResourceUtilsTests.cpp index 69142086765c..011040ba0ebf 100644 --- a/cmds/idmap2/tests/ResourceUtilsTests.cpp +++ b/cmds/idmap2/tests/ResourceUtilsTests.cpp @@ -38,7 +38,7 @@ class ResourceUtilsTests : public Idmap2Tests { apk_assets_ = ApkAssets::Load(GetTargetApkPath()); ASSERT_THAT(apk_assets_, NotNull()); - am_.SetApkAssets({apk_assets_.get()}); + am_.SetApkAssets({apk_assets_}); } const AssetManager2& GetAssetManager() { @@ -47,7 +47,7 @@ class ResourceUtilsTests : public Idmap2Tests { private: AssetManager2 am_; - std::unique_ptr<const ApkAssets> apk_assets_; + AssetManager2::ApkAssetsPtr apk_assets_; }; TEST_F(ResourceUtilsTests, ResToTypeEntryName) { diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp index 5af02f405ed9..0d3ae9b22476 100644 --- a/cmds/incidentd/src/IncidentService.cpp +++ b/cmds/incidentd/src/IncidentService.cpp @@ -502,9 +502,13 @@ status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* switch (code) { case SHELL_COMMAND_TRANSACTION: { - int in = data.readFileDescriptor(); - int out = data.readFileDescriptor(); - int err = data.readFileDescriptor(); + unique_fd in, out, err; + if (status_t status = data.readUniqueFileDescriptor(&in); status != OK) return status; + + if (status_t status = data.readUniqueFileDescriptor(&out); status != OK) return status; + + if (status_t status = data.readUniqueFileDescriptor(&err); status != OK) return status; + int argc = data.readInt32(); Vector<String8> args; for (int i = 0; i < argc && data.dataAvail() > 0; i++) { @@ -514,15 +518,15 @@ status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(data.readStrongBinder()); - FILE* fin = fdopen(in, "r"); - FILE* fout = fdopen(out, "w"); - FILE* ferr = fdopen(err, "w"); + FILE* fin = fdopen(in.release(), "r"); + FILE* fout = fdopen(out.release(), "w"); + FILE* ferr = fdopen(err.release(), "w"); if (fin == NULL || fout == NULL || ferr == NULL) { resultReceiver->send(NO_MEMORY); } else { - err = command(fin, fout, ferr, args); - resultReceiver->send(err); + status_t result = command(fin, fout, ferr, args); + resultReceiver->send(result); } if (fin != NULL) { diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 4e2b6fa56b17..b3dc8a8dffb9 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -245,6 +245,7 @@ interface IActivityTaskManager { * {@link android.view.WindowManagerPolicyConstants#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE} * etc. */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD)") void keyguardGoingAway(int flags); void suppressResizeConfigChanges(boolean suppress); diff --git a/core/java/android/app/IUriGrantsManager.aidl b/core/java/android/app/IUriGrantsManager.aidl index 9e7f2fecfea0..b630d034dca9 100644 --- a/core/java/android/app/IUriGrantsManager.aidl +++ b/core/java/android/app/IUriGrantsManager.aidl @@ -39,4 +39,7 @@ interface IUriGrantsManager { void clearGrantedUriPermissions(in String packageName, int userId); ParceledListSlice getUriPermissions(in String packageName, boolean incoming, boolean persistedOnly); + + int checkGrantUriPermission_ignoreNonSystem( + int sourceUid, String targetPkg, in Uri uri, int modeFlags, int userId); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 54c8cb09d7ea..77b0e913496b 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2890,11 +2890,6 @@ public class Notification implements Parcelable } } - final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON, Person.class); - if (person != null) { - visitor.accept(person.getIconUri()); - } - final RemoteInputHistoryItem[] history = extras.getParcelableArray( Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS, RemoteInputHistoryItem.class); @@ -2906,9 +2901,14 @@ public class Notification implements Parcelable } } } - } - if (isStyle(MessagingStyle.class) && extras != null) { + // Extras for MessagingStyle. We visit them even if not isStyle(MessagingStyle), since + // Notification Listeners might use directly (without the isStyle check). + final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON, Person.class); + if (person != null) { + visitor.accept(person.getIconUri()); + } + final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES, Parcelable.class); if (!ArrayUtils.isEmpty(messages)) { @@ -2938,9 +2938,8 @@ public class Notification implements Parcelable } visitIconUri(visitor, extras.getParcelable(EXTRA_CONVERSATION_ICON, Icon.class)); - } - if (isStyle(CallStyle.class) & extras != null) { + // Extras for CallStyle (same reason for visiting without checking isStyle). Person callPerson = extras.getParcelable(EXTRA_CALL_PERSON, Person.class); if (callPerson != null) { visitor.accept(callPerson.getIconUri()); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index da5e40aedbd2..c561e4b54b01 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -10335,11 +10335,14 @@ public class DevicePolicyManager { * @return the current credential manager policy if null then this policy has not been * configured. */ + @UserHandleAware( + enabledSinceTargetSdkVersion = UPSIDE_DOWN_CAKE, + requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS) public @Nullable PackagePolicy getCredentialManagerPolicy() { throwIfParentInstance("getCredentialManagerPolicy"); if (mService != null) { try { - return mService.getCredentialManagerPolicy(); + return mService.getCredentialManagerPolicy(myUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 003e804831a4..d908d65ea850 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -344,7 +344,7 @@ interface IDevicePolicyManager { boolean hasManagedProfileCallerIdAccess(int userId, String packageName); void setCredentialManagerPolicy(in PackagePolicy policy); - PackagePolicy getCredentialManagerPolicy(); + PackagePolicy getCredentialManagerPolicy(int userId); void setManagedProfileContactsAccessPolicy(in PackagePolicy policy); PackagePolicy getManagedProfileContactsAccessPolicy(); diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index ef3842aeb348..0f284f491c29 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -528,6 +528,10 @@ public final class AssetManager implements AutoCloseable { if (!mOpen) { throw new RuntimeException("AssetManager has been closed"); } + // Let's still check if the native object exists, given all the memory corruptions. + if (mObject == 0) { + throw new RuntimeException("AssetManager is open but the native object is gone"); + } } /** @@ -1153,6 +1157,7 @@ public final class AssetManager implements AutoCloseable { int[] getAttributeResolutionStack(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @StyleRes int xmlStyle) { synchronized (this) { + ensureValidLocked(); return nativeAttributeResolutionStack( mObject, themePtr, xmlStyle, defStyleAttr, defStyleRes); } diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java index 6c0735692db9..c143acb34c5f 100644 --- a/core/java/android/content/res/StringBlock.java +++ b/core/java/android/content/res/StringBlock.java @@ -62,7 +62,7 @@ public final class StringBlock implements Closeable { private static final String TAG = "AssetManager"; private static final boolean localLOGV = false; - private final long mNative; + private long mNative; // final, but gets modified when closed private final boolean mUseSparse; private final boolean mOwnsNative; @@ -207,6 +207,7 @@ public final class StringBlock implements Closeable { if (mOwnsNative) { nativeDestroy(mNative); } + mNative = 0; } } } diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java index 3915a6ccb46d..16fd1f7277a7 100644 --- a/core/java/android/content/res/XmlBlock.java +++ b/core/java/android/content/res/XmlBlock.java @@ -73,7 +73,9 @@ public final class XmlBlock implements AutoCloseable { private void decOpenCountLocked() { mOpenCount--; if (mOpenCount == 0) { + mStrings.close(); nativeDestroy(mNative); + mNative = 0; if (mAssets != null) { mAssets.xmlBlockGone(hashCode()); } @@ -621,7 +623,7 @@ public final class XmlBlock implements AutoCloseable { } private @Nullable final AssetManager mAssets; - private final long mNative; + private long mNative; // final, but gets reset on close /*package*/ final StringBlock mStrings; private boolean mOpen = true; private int mOpenCount = 1; diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp index e9ada235b388..87f9652f8544 100644 --- a/core/jni/android_content_res_ApkAssets.cpp +++ b/core/jni/android_content_res_ApkAssets.cpp @@ -74,17 +74,37 @@ enum : format_type_t { FORMAT_DIRECTORY = 3, }; -Guarded<std::unique_ptr<const ApkAssets>>& ApkAssetsFromLong(jlong ptr) { - return *reinterpret_cast<Guarded<std::unique_ptr<const ApkAssets>>*>(ptr); +Guarded<AssetManager2::ApkAssetsPtr>& ApkAssetsFromLong(jlong ptr) { + return *reinterpret_cast<Guarded<AssetManager2::ApkAssetsPtr>*>(ptr); } -static jlong CreateGuardedApkAssets(std::unique_ptr<const ApkAssets> assets) { - auto guarded_assets = new Guarded<std::unique_ptr<const ApkAssets>>(std::move(assets)); - return reinterpret_cast<jlong>(guarded_assets); +static jlong CreateGuardedApkAssets(AssetManager2::ApkAssetsPtr assets) { + auto guarded_assets = new Guarded<AssetManager2::ApkAssetsPtr>(std::move(assets)); + return reinterpret_cast<jlong>(guarded_assets); } -static void DeleteGuardedApkAssets(Guarded<std::unique_ptr<const ApkAssets>>& apk_assets) { - delete &apk_assets; +static void DeleteGuardedApkAssets(Guarded<AssetManager2::ApkAssetsPtr>& apk_assets) { + apk_assets.safeDelete([&apk_assets](AssetManager2::ApkAssetsPtr* assets) { + if (!assets) { + ALOGW("ApkAssets: Double delete of native assets object %p, ignored", &apk_assets); + } else if (!*assets) { + ALOGW("ApkAssets: Empty native assets pointer in native assets object %p", &apk_assets); + } else { + // |RefBase| increments |StrongCount| for each |sp<>| instance, and |WeakCount| for + // both |sp<>| and |wp<>| instances. This means the actual |wp<>| instance count + // is |WeakCount - StrongCount|. + const auto useCount = (*assets)->getStrongCount(); + const auto weakCount = (*assets)->getWeakRefs()->getWeakCount() - useCount; + if (useCount > 1) { + ALOGW("ApkAssets: Deleting an object '%s' with %d > 1 strong and %d weak references", + (*assets)->GetDebugName().c_str(), int(useCount), int(weakCount)); + } else if (weakCount > 0) { + ALOGW("ApkAssets: Deleting an ApkAssets object '%s' with %d weak references", + (*assets)->GetDebugName().c_str(), int(weakCount)); + } + } + }); + delete &apk_assets; } class LoaderAssetsProvider : public AssetsProvider { @@ -209,7 +229,7 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma ATRACE_NAME(base::StringPrintf("LoadApkAssets(%s)", path.c_str()).c_str()); auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider); - std::unique_ptr<ApkAssets> apk_assets; + AssetManager2::ApkAssetsPtr apk_assets; switch (format) { case FORMAT_APK: { auto assets = MultiAssetsProvider::Create(std::move(loader_assets), @@ -269,7 +289,7 @@ static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, const format_type_t } auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider); - std::unique_ptr<const ApkAssets> apk_assets; + AssetManager2::ApkAssetsPtr apk_assets; switch (format) { case FORMAT_APK: { auto assets = @@ -336,7 +356,7 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_ } auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider); - std::unique_ptr<const ApkAssets> apk_assets; + AssetManager2::ApkAssetsPtr apk_assets; switch (format) { case FORMAT_APK: { auto assets = @@ -374,11 +394,17 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_ static jlong NativeLoadEmpty(JNIEnv* env, jclass /*clazz*/, jint flags, jobject assets_provider) { auto apk_assets = ApkAssets::Load(LoaderAssetsProvider::Create(env, assets_provider), flags); + if (apk_assets == nullptr) { + const std::string error_msg = base::StringPrintf("Failed to load empty assets with provider %p", + (void*)assets_provider); + jniThrowException(env, "java/io/IOException", error_msg.c_str()); + return 0; + } return CreateGuardedApkAssets(std::move(apk_assets)); } static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) { - DeleteGuardedApkAssets(ApkAssetsFromLong(ptr)); + DeleteGuardedApkAssets(ApkAssetsFromLong(ptr)); } static jstring NativeGetAssetPath(JNIEnv* env, jclass /*clazz*/, jlong ptr) { diff --git a/core/jni/android_content_res_ApkAssets.h b/core/jni/android_content_res_ApkAssets.h index 7e525dc75ef0..8159a53caaa5 100644 --- a/core/jni/android_content_res_ApkAssets.h +++ b/core/jni/android_content_res_ApkAssets.h @@ -18,13 +18,13 @@ #define ANDROID_CONTENT_RES_APKASSETS_H #include "androidfw/ApkAssets.h" +#include "androidfw/AssetManager2.h" #include "androidfw/MutexGuard.h" - #include "jni.h" namespace android { -Guarded<std::unique_ptr<const ApkAssets>>& ApkAssetsFromLong(jlong ptr); +Guarded<AssetManager2::ApkAssetsPtr>& ApkAssetsFromLong(jlong ptr); } // namespace android diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index a2205eb7dfdb..fc53a766b772 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -17,6 +17,9 @@ #define ATRACE_TAG ATRACE_TAG_RESOURCES #define LOG_TAG "asset" +#include "android_runtime/android_util_AssetManager.h" + +#include <errno.h> #include <inttypes.h> #include <linux/capability.h> #include <stdio.h> @@ -31,7 +34,7 @@ #include "android-base/logging.h" #include "android-base/properties.h" #include "android-base/stringprintf.h" -#include "android_runtime/android_util_AssetManager.h" +#include "android_content_res_ApkAssets.h" #include "android_runtime/AndroidRuntime.h" #include "android_util_Binder.h" #include "androidfw/Asset.h" @@ -39,11 +42,9 @@ #include "androidfw/AssetManager2.h" #include "androidfw/AttributeResolution.h" #include "androidfw/MutexGuard.h" -#include <androidfw/ResourceTimer.h> +#include "androidfw/ResourceTimer.h" #include "androidfw/ResourceTypes.h" #include "androidfw/ResourceUtils.h" - -#include "android_content_res_ApkAssets.h" #include "core_jni_helpers.h" #include "jni.h" #include "nativehelper/JNIPlatformHelp.h" @@ -161,9 +162,30 @@ static Guarded<AssetManager2>& AssetManagerFromLong(jlong ptr) { return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr)); } +struct ScopedLockedAssetsOperation { + ScopedLockedAssetsOperation(Guarded<AssetManager2>& guarded_am) + : am_(guarded_am), op_(am_->StartOperation()) {} + + AssetManager2& operator*() { return *am_; } + + AssetManager2* operator->() { return am_.get(); } + + AssetManager2* get() { return am_.get(); } + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedLockedAssetsOperation); + + ScopedLock<AssetManager2> am_; + AssetManager2::ScopedOperation op_; +}; + +ScopedLockedAssetsOperation LockAndStartAssetManager(jlong ptr) { + return ScopedLockedAssetsOperation(AssetManagerFromLong(ptr)); +} + static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring package_name) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); const ScopedUtfChars package_name_utf8(env, package_name); CHECK(package_name_utf8.c_str() != nullptr); const std::string std_package_name(package_name_utf8.c_str()); @@ -209,7 +231,7 @@ static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr, static jstring NativeGetOverlayablesToString(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring package_name) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); const ScopedUtfChars package_name_utf8(env, package_name); CHECK(package_name_utf8.c_str() != nullptr); const std::string std_package_name(package_name_utf8.c_str()); @@ -296,7 +318,7 @@ static void NativeSetApkAssets(JNIEnv* env, jclass /*clazz*/, jlong ptr, ATRACE_NAME("AssetManager::SetApkAssets"); const jsize apk_assets_len = env->GetArrayLength(apk_assets_array); - std::vector<const ApkAssets*> apk_assets; + std::vector<AssetManager2::ApkAssetsPtr> apk_assets; apk_assets.reserve(apk_assets_len); for (jsize i = 0; i < apk_assets_len; i++) { jobject obj = env->GetObjectArrayElement(apk_assets_array, i); @@ -310,12 +332,17 @@ static void NativeSetApkAssets(JNIEnv* env, jclass /*clazz*/, jlong ptr, if (env->ExceptionCheck()) { return; } - + if (!apk_assets_native_ptr) { + ALOGW("Got a closed ApkAssets instance at index %d for AssetManager %p", i, (void*)ptr); + std::string msg = StringPrintf("ApkAssets at index %d is closed, native pointer is null", i); + jniThrowException(env, "java/lang/IllegalArgumentException", msg.c_str()); + return; + } auto scoped_assets = ScopedLock(ApkAssetsFromLong(apk_assets_native_ptr)); - apk_assets.push_back(scoped_assets->get()); + apk_assets.emplace_back(*scoped_assets); } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); assetmanager->SetApkAssets(apk_assets, invalidate_caches); } @@ -365,14 +392,14 @@ static void NativeSetConfiguration(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin configuration.screenLayout2 = static_cast<uint8_t>((screen_layout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); assetmanager->SetConfiguration(configuration); } static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr, jboolean includeOverlays, jboolean includeLoaders) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); jobject sparse_array = env->NewObject(gSparseArrayOffsets.classObject, gSparseArrayOffsets.constructor); @@ -402,7 +429,7 @@ static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/ } static jboolean ContainsAllocatedTable(JNIEnv* env, jclass /*clazz*/, jlong ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); return assetmanager->ContainsAllocatedTable(); } @@ -413,7 +440,7 @@ static jobjectArray NativeList(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring return nullptr; } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<AssetDir> asset_dir = assetmanager->OpenDir(path_utf8.c_str()); if (asset_dir == nullptr) { @@ -461,7 +488,7 @@ static jlong NativeOpenAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring a return 0; } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset = assetmanager->Open(asset_path_utf8.c_str(), static_cast<Asset::AccessMode>(access_mode)); if (!asset) { @@ -481,7 +508,7 @@ static jobject NativeOpenAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstri ATRACE_NAME(base::StringPrintf("AssetManager::OpenAssetFd(%s)", asset_path_utf8.c_str()).c_str()); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset = assetmanager->Open(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM); if (!asset) { jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str()); @@ -507,7 +534,7 @@ static jlong NativeOpenNonAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint j return 0; } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset; if (cookie != kInvalidCookie) { asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, @@ -535,7 +562,7 @@ static jobject NativeOpenNonAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, ji ATRACE_NAME(base::StringPrintf("AssetManager::OpenNonAssetFd(%s)", asset_path_utf8.c_str()).c_str()); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset; if (cookie != kInvalidCookie) { asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM); @@ -561,7 +588,7 @@ static jlong NativeOpenXmlAsset(JNIEnv* env, jobject /*clazz*/, jlong ptr, jint ATRACE_NAME(base::StringPrintf("AssetManager::OpenXmlAsset(%s)", asset_path_utf8.c_str()).c_str()); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset; if (cookie != kInvalidCookie) { asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM); @@ -609,7 +636,8 @@ static jlong NativeOpenXmlAssetFd(JNIEnv* env, jobject /*clazz*/, jlong ptr, int std::unique_ptr<Asset> asset(Asset::createFromFd(dup_fd.release(), nullptr, Asset::AccessMode::ACCESS_BUFFER)); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie); const incfs::map_ptr<void> buffer = asset->getIncFsBuffer(true /* aligned */); @@ -632,8 +660,9 @@ static jlong NativeOpenXmlAssetFd(JNIEnv* env, jobject /*clazz*/, jlong ptr, int static jint NativeGetResourceValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid, jshort density, jobject typed_value, jboolean resolve_references) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); ResourceTimer _timer(ResourceTimer::Counter::GetResourceValue); + auto value = assetmanager->GetResource(static_cast<uint32_t>(resid), false /*may_be_bag*/, static_cast<uint16_t>(density)); if (!value.has_value()) { @@ -651,7 +680,8 @@ static jint NativeGetResourceValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin static jint NativeGetResourceBagValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid, jint bag_entry_id, jobject typed_value) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag.has_value()) { return ApkAssetsCookieToJavaCookie(kInvalidCookie); @@ -678,7 +708,8 @@ static jint NativeGetResourceBagValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, } static jintArray NativeGetStyleAttributes(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag_result.has_value()) { return nullptr; @@ -699,7 +730,8 @@ static jintArray NativeGetStyleAttributes(JNIEnv* env, jclass /*clazz*/, jlong p static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag_result.has_value()) { return nullptr; @@ -720,31 +752,36 @@ static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, } if (attr_value.type == Res_value::TYPE_STRING) { - const ApkAssets* apk_assets = assetmanager->GetApkAssets()[attr_value.cookie]; - const ResStringPool* pool = apk_assets->GetLoadedArsc()->GetStringPool(); + const auto& apk_assets = assetmanager->GetApkAssets(attr_value.cookie); + if (apk_assets) { + const ResStringPool* pool = apk_assets->GetLoadedArsc()->GetStringPool(); + + jstring java_string; + if (auto str_utf8 = pool->string8At(attr_value.data); str_utf8.has_value()) { + java_string = env->NewStringUTF(str_utf8->data()); + } else { + auto str_utf16 = pool->stringAt(attr_value.data); + if (!str_utf16.has_value()) { + return nullptr; + } + java_string = env->NewString(reinterpret_cast<const jchar*>(str_utf16->data()), + str_utf16->size()); + } - jstring java_string; - if (auto str_utf8 = pool->string8At(attr_value.data); str_utf8.has_value()) { - java_string = env->NewStringUTF(str_utf8->data()); - } else { - auto str_utf16 = pool->stringAt(attr_value.data); - if (!str_utf16.has_value()) { + // Check for errors creating the strings (if malformed or no memory). + if (env->ExceptionCheck()) { return nullptr; } - java_string = env->NewString(reinterpret_cast<const jchar*>(str_utf16->data()), - str_utf16->size()); - } - - // Check for errors creating the strings (if malformed or no memory). - if (env->ExceptionCheck()) { - return nullptr; - } - env->SetObjectArrayElement(array, i, java_string); + env->SetObjectArrayElement(array, i, java_string); - // If we have a large amount of string in our array, we might overflow the - // local reference table of the VM. - env->DeleteLocalRef(java_string); + // If we have a large amount of string in our array, we might overflow the + // local reference table of the VM. + env->DeleteLocalRef(java_string); + } else { + ALOGW("NativeGetResourceStringArray: an expired assets object #%d / %d", i, + attr_value.cookie); + } } } return array; @@ -752,7 +789,8 @@ static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, static jintArray NativeGetResourceStringArrayInfo(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag_result.has_value()) { return nullptr; @@ -790,7 +828,8 @@ static jintArray NativeGetResourceStringArrayInfo(JNIEnv* env, jclass /*clazz*/, } static jintArray NativeGetResourceIntArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag_result.has_value()) { return nullptr; @@ -825,21 +864,22 @@ static jintArray NativeGetResourceIntArray(JNIEnv* env, jclass /*clazz*/, jlong } static jint NativeGetResourceArraySize(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); - auto bag = assetmanager->GetBag(static_cast<uint32_t>(resid)); - if (!bag.has_value()) { - return -1; - } + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag = assetmanager->GetBag(static_cast<uint32_t>(resid)); + if (!bag.has_value()) { + return -1; + } return static_cast<jint>((*bag)->entry_count); } static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid, jintArray out_data) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); - auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); - if (!bag_result.has_value()) { + auto assetmanager = LockAndStartAssetManager(ptr); + + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); + if (!bag_result.has_value()) { return -1; - } + } const jsize out_data_length = env->GetArrayLength(out_data); if (env->ExceptionCheck()) { @@ -886,7 +926,7 @@ static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin } static jint NativeGetParentThemeIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); const auto parentThemeResId = assetmanager->GetParentThemeResourceId(resid); return parentThemeResId.value_or(0); } @@ -913,7 +953,7 @@ static jint NativeGetResourceIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr package = package_utf8.c_str(); } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto resid = assetmanager->GetResourceId(name_utf8.c_str(), type, package); if (!resid.has_value()) { return 0; @@ -923,7 +963,7 @@ static jint NativeGetResourceIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr } static jstring NativeGetResourceName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid)); if (!name.has_value()) { return nullptr; @@ -934,7 +974,7 @@ static jstring NativeGetResourceName(JNIEnv* env, jclass /*clazz*/, jlong ptr, j } static jstring NativeGetResourcePackageName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid)); if (!name.has_value()) { return nullptr; @@ -947,7 +987,7 @@ static jstring NativeGetResourcePackageName(JNIEnv* env, jclass /*clazz*/, jlong } static jstring NativeGetResourceTypeName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid)); if (!name.has_value()) { return nullptr; @@ -962,7 +1002,7 @@ static jstring NativeGetResourceTypeName(JNIEnv* env, jclass /*clazz*/, jlong pt } static jstring NativeGetResourceEntryName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid)); if (!name.has_value()) { return nullptr; @@ -980,14 +1020,14 @@ static void NativeSetResourceResolutionLoggingEnabled(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jboolean enabled) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); assetmanager->SetResourceResolutionLoggingEnabled(enabled); } static jstring NativeGetLastResourceResolution(JNIEnv* env, jclass /*clazz*/, jlong ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::string resolution = assetmanager->GetLastResourceResolution(); if (resolution.empty()) { return nullptr; @@ -998,7 +1038,7 @@ static jstring NativeGetLastResourceResolution(JNIEnv* env, static jobjectArray NativeGetLocales(JNIEnv* env, jclass /*class*/, jlong ptr, jboolean exclude_system) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::set<std::string> locales = assetmanager->GetResourceLocales(exclude_system, true /*merge_equivalent_languages*/); @@ -1036,7 +1076,7 @@ static jobject ConstructConfigurationObject(JNIEnv* env, const ResTable_config& } static jobjectArray GetSizeAndUiModeConfigurations(JNIEnv* env, jlong ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto configurations = assetmanager->GetResourceConfigurations(true /*exclude_system*/, false /*exclude_mipmap*/); if (!configurations.has_value()) { @@ -1070,12 +1110,10 @@ static jobjectArray NativeGetSizeAndUiModeConfigurations(JNIEnv* env, jclass /*c return GetSizeAndUiModeConfigurations(env, ptr); } -static jintArray NativeAttributeResolutionStack( - JNIEnv* env, jclass /*clazz*/, jlong ptr, - jlong theme_ptr, jint xml_style_res, - jint def_style_attr, jint def_style_resid) { - - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); +static jintArray NativeAttributeResolutionStack(JNIEnv* env, jclass /*clazz*/, jlong ptr, + jlong theme_ptr, jint xml_style_res, + jint def_style_attr, jint def_style_resid) { + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1110,7 +1148,7 @@ static jintArray NativeAttributeResolutionStack( static void NativeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint def_style_attr, jint def_style_resid, jlong xml_parser_ptr, jintArray java_attrs, jlong out_values_ptr, jlong out_indices_ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1185,7 +1223,7 @@ static jboolean NativeResolveAttrs(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlo } } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1244,7 +1282,7 @@ static jboolean NativeRetrieveAttributes(JNIEnv* env, jclass /*clazz*/, jlong pt } } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); ResourceTimer _timer(ResourceTimer::Counter::RetrieveAttributes); ResXMLParser* xml_parser = reinterpret_cast<ResXMLParser*>(xml_parser_ptr); auto result = @@ -1262,7 +1300,7 @@ static jboolean NativeRetrieveAttributes(JNIEnv* env, jclass /*clazz*/, jlong pt } static jlong NativeThemeCreate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); return reinterpret_cast<jlong>(assetmanager->NewTheme().release()); } @@ -1277,7 +1315,7 @@ static jlong NativeGetThemeFreeFunction(JNIEnv* /*env*/, jclass /*clazz*/) { static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint resid, jboolean force) { // AssetManager is accessed via the theme, so grab an explicit lock here. - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1295,7 +1333,7 @@ static void NativeThemeRebase(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong th jint style_count) { // Lock both the original asset manager of the theme and the new asset manager to be used for the // theme. - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); uint32_t* style_id_args = nullptr; if (style_ids != nullptr) { @@ -1338,25 +1376,23 @@ static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_asset_manag Theme* dst_theme = reinterpret_cast<Theme*>(dst_theme_ptr); Theme* src_theme = reinterpret_cast<Theme*>(src_theme_ptr); - ScopedLock<AssetManager2> src_assetmanager(AssetManagerFromLong(src_asset_manager_ptr)); + auto src_assetmanager = LockAndStartAssetManager(src_asset_manager_ptr); CHECK(src_theme->GetAssetManager() == &(*src_assetmanager)); - (void) src_assetmanager; if (dst_asset_manager_ptr != src_asset_manager_ptr) { - ScopedLock<AssetManager2> dst_assetmanager(AssetManagerFromLong(dst_asset_manager_ptr)); + auto dst_assetmanager = LockAndStartAssetManager(dst_asset_manager_ptr); CHECK(dst_theme->GetAssetManager() == &(*dst_assetmanager)); - (void) dst_assetmanager; - dst_theme->SetTo(*src_theme); } else { - dst_theme->SetTo(*src_theme); + dst_theme->SetTo(*src_theme); } } static jint NativeThemeGetAttributeValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint resid, jobject typed_value, jboolean resolve_references) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1379,7 +1415,7 @@ static jint NativeThemeGetAttributeValue(JNIEnv* env, jclass /*clazz*/, jlong pt static void NativeThemeDump(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint priority, jstring tag, jstring prefix) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp index 15aaae25f754..f0c639574a9f 100644 --- a/libs/androidfw/ApkAssets.cpp +++ b/libs/androidfw/ApkAssets.cpp @@ -27,39 +27,34 @@ using base::unique_fd; constexpr const char* kResourcesArsc = "resources.arsc"; -ApkAssets::ApkAssets(std::unique_ptr<Asset> resources_asset, +ApkAssets::ApkAssets(PrivateConstructorUtil, std::unique_ptr<Asset> resources_asset, std::unique_ptr<LoadedArsc> loaded_arsc, - std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap) + std::unique_ptr<AssetsProvider> assets, package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, std::unique_ptr<LoadedIdmap> loaded_idmap) : resources_asset_(std::move(resources_asset)), loaded_arsc_(std::move(loaded_arsc)), assets_provider_(std::move(assets)), property_flags_(property_flags), idmap_asset_(std::move(idmap_asset)), - loaded_idmap_(std::move(loaded_idmap)) {} + loaded_idmap_(std::move(loaded_idmap)) { +} -std::unique_ptr<ApkAssets> ApkAssets::Load(const std::string& path, package_property_t flags) { +ApkAssetsPtr ApkAssets::Load(const std::string& path, package_property_t flags) { return Load(ZipAssetsProvider::Create(path, flags), flags); } -std::unique_ptr<ApkAssets> ApkAssets::LoadFromFd(base::unique_fd fd, - const std::string& debug_name, - package_property_t flags, - off64_t offset, - off64_t len) { +ApkAssetsPtr ApkAssets::LoadFromFd(base::unique_fd fd, const std::string& debug_name, + package_property_t flags, off64_t offset, off64_t len) { return Load(ZipAssetsProvider::Create(std::move(fd), debug_name, offset, len), flags); } -std::unique_ptr<ApkAssets> ApkAssets::Load(std::unique_ptr<AssetsProvider> assets, - package_property_t flags) { +ApkAssetsPtr ApkAssets::Load(std::unique_ptr<AssetsProvider> assets, package_property_t flags) { return LoadImpl(std::move(assets), flags, nullptr /* idmap_asset */, nullptr /* loaded_idmap */); } -std::unique_ptr<ApkAssets> ApkAssets::LoadTable(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, - package_property_t flags) { +ApkAssetsPtr ApkAssets::LoadTable(std::unique_ptr<Asset> resources_asset, + std::unique_ptr<AssetsProvider> assets, + package_property_t flags) { if (resources_asset == nullptr) { return {}; } @@ -67,8 +62,7 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadTable(std::unique_ptr<Asset> resources nullptr /* loaded_idmap */); } -std::unique_ptr<ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path, - package_property_t flags) { +ApkAssetsPtr ApkAssets::LoadOverlay(const std::string& idmap_path, package_property_t flags) { CHECK((flags & PROPERTY_LOADER) == 0U) << "Cannot load RROs through loaders"; auto idmap_asset = AssetsProvider::CreateAssetFromFile(idmap_path); if (idmap_asset == nullptr) { @@ -103,10 +97,10 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path, std::move(loaded_idmap)); } -std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap) { +ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, + std::unique_ptr<LoadedIdmap> loaded_idmap) { if (assets == nullptr) { return {}; } @@ -125,11 +119,11 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<AssetsProvider> a std::move(idmap_asset), std::move(loaded_idmap)); } -std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap) { +ApkAssetsPtr ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_asset, + std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, + std::unique_ptr<LoadedIdmap> loaded_idmap) { if (assets == nullptr ) { return {}; } @@ -155,10 +149,9 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_ return {}; } - return std::unique_ptr<ApkAssets>(new ApkAssets(std::move(resources_asset), - std::move(loaded_arsc), std::move(assets), - property_flags, std::move(idmap_asset), - std::move(loaded_idmap))); + return ApkAssetsPtr::make(PrivateConstructorUtil{}, std::move(resources_asset), + std::move(loaded_arsc), std::move(assets), property_flags, + std::move(idmap_asset), std::move(loaded_idmap)); } std::optional<std::string_view> ApkAssets::GetPath() const { @@ -174,4 +167,5 @@ bool ApkAssets::IsUpToDate() const { return IsLoader() || ((!loaded_idmap_ || loaded_idmap_->IsUpToDate()) && assets_provider_->IsUpToDate()); } + } // namespace android diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index 68f5e4a88c7e..d33b592bddc6 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -91,13 +91,14 @@ struct FindEntryResult { StringPoolRef entry_string_ref; }; -AssetManager2::AssetManager2() { - memset(&configuration_, 0, sizeof(configuration_)); +AssetManager2::AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration) + : configuration_(configuration) { + // Don't invalidate caches here as there's nothing cached yet. + SetApkAssets(apk_assets, false); } -bool AssetManager2::SetApkAssets(std::vector<const ApkAssets*> apk_assets, bool invalidate_caches) { - apk_assets_ = std::move(apk_assets); - BuildDynamicRefTable(); +bool AssetManager2::SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches) { + BuildDynamicRefTable(apk_assets); RebuildFilterList(); if (invalidate_caches) { InvalidateCaches(static_cast<uint32_t>(-1)); @@ -105,7 +106,21 @@ bool AssetManager2::SetApkAssets(std::vector<const ApkAssets*> apk_assets, bool return true; } -void AssetManager2::BuildDynamicRefTable() { +bool AssetManager2::SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets, + bool invalidate_caches) { + return SetApkAssets(ApkAssetsList(apk_assets.begin(), apk_assets.size()), invalidate_caches); +} + +void AssetManager2::BuildDynamicRefTable(ApkAssetsList apk_assets) { + auto op = StartOperation(); + + apk_assets_.resize(apk_assets.size()); + for (size_t i = 0; i != apk_assets.size(); ++i) { + apk_assets_[i].first = apk_assets[i]; + // Let's populate the locked assets right away as we're going to need them here later. + apk_assets_[i].second = apk_assets[i]; + } + package_groups_.clear(); package_ids_.fill(0xff); @@ -116,16 +131,19 @@ void AssetManager2::BuildDynamicRefTable() { // Overlay resources are not directly referenced by an application so their resource ids // can change throughout the application's lifetime. Assign overlay package ids last. - std::vector<const ApkAssets*> sorted_apk_assets(apk_assets_); - std::stable_partition(sorted_apk_assets.begin(), sorted_apk_assets.end(), [](const ApkAssets* a) { - return !a->IsOverlay(); - }); + std::vector<const ApkAssets*> sorted_apk_assets; + sorted_apk_assets.reserve(apk_assets.size()); + for (auto& asset : apk_assets) { + sorted_apk_assets.push_back(asset.get()); + } + std::stable_partition(sorted_apk_assets.begin(), sorted_apk_assets.end(), + [](auto a) { return !a->IsOverlay(); }); // The assets cookie must map to the position of the apk assets in the unsorted apk assets list. std::unordered_map<const ApkAssets*, ApkAssetsCookie> apk_assets_cookies; - apk_assets_cookies.reserve(apk_assets_.size()); - for (size_t i = 0, n = apk_assets_.size(); i < n; i++) { - apk_assets_cookies[apk_assets_[i]] = static_cast<ApkAssetsCookie>(i); + apk_assets_cookies.reserve(apk_assets.size()); + for (size_t i = 0, n = apk_assets.size(); i < n; i++) { + apk_assets_cookies[apk_assets[i].get()] = static_cast<ApkAssetsCookie>(i); } // 0x01 is reserved for the android package. @@ -240,9 +258,11 @@ void AssetManager2::BuildDynamicRefTable() { void AssetManager2::DumpToLog() const { LOG(INFO) << base::StringPrintf("AssetManager2(this=%p)", this); + auto op = StartOperation(); std::string list; - for (const auto& apk_assets : apk_assets_) { - base::StringAppendF(&list, "%s,", apk_assets->GetDebugName().c_str()); + for (size_t i = 0; i < apk_assets_.size(); ++i) { + const auto& assets = GetApkAssets(i); + base::StringAppendF(&list, "%s,", assets ? assets->GetDebugName().c_str() : "nullptr"); } LOG(INFO) << "ApkAssets: " << list; @@ -279,7 +299,9 @@ const ResStringPool* AssetManager2::GetStringPoolForCookie(ApkAssetsCookie cooki if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) { return nullptr; } - return apk_assets_[cookie]->GetLoadedArsc()->GetStringPool(); + auto op = StartOperation(); + const auto& assets = GetApkAssets(cookie); + return assets ? assets->GetLoadedArsc()->GetStringPool() : nullptr; } const DynamicRefTable* AssetManager2::GetDynamicRefTableForPackage(uint32_t package_id) const { @@ -329,9 +351,14 @@ const std::unordered_map<std::string, std::string>* bool AssetManager2::GetOverlayablesToString(android::StringPiece package_name, std::string* out) const { + auto op = StartOperation(); uint8_t package_id = 0U; - for (const auto& apk_assets : apk_assets_) { - const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc(); + for (size_t i = 0; i != apk_assets_.size(); ++i) { + const auto& assets = GetApkAssets(i); + if (!assets) { + continue; + } + const LoadedArsc* loaded_arsc = assets->GetLoadedArsc(); if (loaded_arsc == nullptr) { continue; } @@ -384,8 +411,14 @@ bool AssetManager2::GetOverlayablesToString(android::StringPiece package_name, } bool AssetManager2::ContainsAllocatedTable() const { - return std::find_if(apk_assets_.begin(), apk_assets_.end(), - std::mem_fn(&ApkAssets::IsTableAllocated)) != apk_assets_.end(); + auto op = StartOperation(); + for (size_t i = 0; i != apk_assets_.size(); ++i) { + const auto& assets = GetApkAssets(i); + if (assets && assets->IsTableAllocated()) { + return true; + } + } + return false; } void AssetManager2::SetConfiguration(const ResTable_config& configuration) { @@ -398,8 +431,8 @@ void AssetManager2::SetConfiguration(const ResTable_config& configuration) { } } -std::set<const ApkAssets*> AssetManager2::GetNonSystemOverlays() const { - std::set<const ApkAssets*> non_system_overlays; +std::set<AssetManager2::ApkAssetsPtr> AssetManager2::GetNonSystemOverlays() const { + std::set<ApkAssetsPtr> non_system_overlays; for (const PackageGroup& package_group : package_groups_) { bool found_system_package = false; for (const ConfiguredPackage& package : package_group.packages_) { @@ -410,8 +443,11 @@ std::set<const ApkAssets*> AssetManager2::GetNonSystemOverlays() const { } if (!found_system_package) { + auto op = StartOperation(); for (const ConfiguredOverlay& overlay : package_group.overlays_) { - non_system_overlays.insert(apk_assets_[overlay.cookie]); + if (const auto& asset = GetApkAssets(overlay.cookie)) { + non_system_overlays.insert(std::move(asset)); + } } } } @@ -422,22 +458,27 @@ std::set<const ApkAssets*> AssetManager2::GetNonSystemOverlays() const { base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceConfigurations( bool exclude_system, bool exclude_mipmap) const { ATRACE_NAME("AssetManager::GetResourceConfigurations"); + auto op = StartOperation(); + const auto non_system_overlays = - (exclude_system) ? GetNonSystemOverlays() : std::set<const ApkAssets*>(); + exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>(); std::set<ResTable_config> configurations; for (const PackageGroup& package_group : package_groups_) { for (size_t i = 0; i < package_group.packages_.size(); i++) { const ConfiguredPackage& package = package_group.packages_[i]; - if (exclude_system && package.loaded_package_->IsSystem()) { - continue; - } - - auto apk_assets = apk_assets_[package_group.cookies_[i]]; - if (exclude_system && apk_assets->IsOverlay() && - non_system_overlays.find(apk_assets) == non_system_overlays.end()) { - // Exclude overlays that target system resources. - continue; + if (exclude_system) { + if (package.loaded_package_->IsSystem()) { + continue; + } + if (!non_system_overlays.empty()) { + // Exclude overlays that target only system resources. + const auto& apk_assets = GetApkAssets(package_group.cookies_[i]); + if (apk_assets && apk_assets->IsOverlay() && + non_system_overlays.find(apk_assets) == non_system_overlays.end()) { + continue; + } + } } auto result = package.loaded_package_->CollectConfigurations(exclude_mipmap, &configurations); @@ -452,22 +493,27 @@ base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceCon std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system, bool merge_equivalent_languages) const { ATRACE_NAME("AssetManager::GetResourceLocales"); + auto op = StartOperation(); + std::set<std::string> locales; const auto non_system_overlays = - (exclude_system) ? GetNonSystemOverlays() : std::set<const ApkAssets*>(); + exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>(); for (const PackageGroup& package_group : package_groups_) { for (size_t i = 0; i < package_group.packages_.size(); i++) { const ConfiguredPackage& package = package_group.packages_[i]; - if (exclude_system && package.loaded_package_->IsSystem()) { - continue; - } - - auto apk_assets = apk_assets_[package_group.cookies_[i]]; - if (exclude_system && apk_assets->IsOverlay() && - non_system_overlays.find(apk_assets) == non_system_overlays.end()) { - // Exclude overlays that target system resources. - continue; + if (exclude_system) { + if (package.loaded_package_->IsSystem()) { + continue; + } + if (!non_system_overlays.empty()) { + // Exclude overlays that target only system resources. + const auto& apk_assets = GetApkAssets(package_group.cookies_[i]); + if (apk_assets && apk_assets->IsOverlay() && + non_system_overlays.find(apk_assets) == non_system_overlays.end()) { + continue; + } + } } package.loaded_package_->CollectLocales(merge_equivalent_languages, &locales); @@ -490,15 +536,15 @@ std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAsset std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) const { ATRACE_NAME("AssetManager::OpenDir"); + auto op = StartOperation(); std::string full_path = "assets/" + dirname; - std::unique_ptr<SortedVector<AssetDir::FileInfo>> files = - util::make_unique<SortedVector<AssetDir::FileInfo>>(); + auto files = util::make_unique<SortedVector<AssetDir::FileInfo>>(); // Start from the back. - for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) { - const ApkAssets* apk_assets = *iter; - if (apk_assets->IsOverlay()) { + for (size_t i = apk_assets_.size(); i > 0; --i) { + const auto& apk_assets = GetApkAssets(i - 1); + if (!apk_assets || apk_assets->IsOverlay()) { continue; } @@ -526,15 +572,17 @@ std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) con std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename, Asset::AccessMode mode, ApkAssetsCookie* out_cookie) const { - for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) { + auto op = StartOperation(); + for (size_t i = apk_assets_.size(); i > 0; i--) { + const auto& assets = GetApkAssets(i - 1); // Prevent RRO from modifying assets and other entries accessed by file // path. Explicitly asking for a path in a given package (denoted by a // cookie) is still OK. - if (apk_assets_[i]->IsOverlay()) { + if (!assets || assets->IsOverlay()) { continue; } - std::unique_ptr<Asset> asset = apk_assets_[i]->GetAssetsProvider()->Open(filename, mode); + std::unique_ptr<Asset> asset = assets->GetAssetsProvider()->Open(filename, mode); if (asset) { if (out_cookie != nullptr) { *out_cookie = i; @@ -555,7 +603,9 @@ std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename, if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) { return {}; } - return apk_assets_[cookie]->GetAssetsProvider()->Open(filename, mode); + auto op = StartOperation(); + const auto& assets = GetApkAssets(cookie); + return assets ? assets->GetAssetsProvider()->Open(filename, mode) : nullptr; } base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( @@ -568,6 +618,8 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( last_resolution_.resid = resid; } + auto op = StartOperation(); + // Might use this if density_override != 0. ResTable_config density_override_config; @@ -603,90 +655,97 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( } bool overlaid = false; - if (!stop_at_first_match && !ignore_configuration && !apk_assets_[result->cookie]->IsLoader()) { - for (const auto& id_map : package_group.overlays_) { - auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid); - if (!overlay_entry) { - // No id map entry exists for this target resource. - continue; - } - if (overlay_entry.IsInlineValue()) { - // The target resource is overlaid by an inline value not represented by a resource. - ConfigDescription best_frro_config; - Res_value best_frro_value; - bool frro_found = false; - for( const auto& [config, value] : overlay_entry.GetInlineValue()) { - if ((!frro_found || config.isBetterThan(best_frro_config, desired_config)) - && config.match(*desired_config)) { - frro_found = true; - best_frro_config = config; - best_frro_value = value; - } - } - if (!frro_found) { + if (!stop_at_first_match && !ignore_configuration) { + const auto& assets = GetApkAssets(result->cookie); + if (!assets) { + ALOGE("Found expired ApkAssets #%d for resource ID 0x%08x.", result->cookie, resid); + return base::unexpected(std::nullopt); + } + if (!assets->IsLoader()) { + for (const auto& id_map : package_group.overlays_) { + auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid); + if (!overlay_entry) { + // No id map entry exists for this target resource. continue; } - result->entry = best_frro_value; - result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); - result->cookie = id_map.cookie; - - if (UNLIKELY(logging_enabled)) { - last_resolution_.steps.push_back( - Resolution::Step{Resolution::Step::Type::OVERLAID_INLINE, String8(), result->cookie}); - if (auto path = apk_assets_[result->cookie]->GetPath()) { - const std::string overlay_path = path->data(); - if (IsFabricatedOverlay(overlay_path)) { - // FRRO don't have package name so we use the creating package here. - String8 frro_name = String8("FRRO"); - // Get the first part of it since the expected one should be like - // {overlayPackageName}-{overlayName}-{4 alphanumeric chars}.frro - // under /data/resource-cache/. - const std::string name = overlay_path.substr(overlay_path.rfind('/') + 1); - const size_t end = name.find('-'); - if (frro_name.size() != overlay_path.size() && end != std::string::npos) { - frro_name.append(base::StringPrintf(" created by %s", - name.substr(0 /* pos */, - end).c_str()).c_str()); + if (overlay_entry.IsInlineValue()) { + // The target resource is overlaid by an inline value not represented by a resource. + ConfigDescription best_frro_config; + Res_value best_frro_value; + bool frro_found = false; + for( const auto& [config, value] : overlay_entry.GetInlineValue()) { + if ((!frro_found || config.isBetterThan(best_frro_config, desired_config)) + && config.match(*desired_config)) { + frro_found = true; + best_frro_config = config; + best_frro_value = value; + } + } + if (!frro_found) { + continue; + } + result->entry = best_frro_value; + result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); + result->cookie = id_map.cookie; + + if (UNLIKELY(logging_enabled)) { + last_resolution_.steps.push_back( + Resolution::Step{Resolution::Step::Type::OVERLAID_INLINE, String8(), result->cookie}); + if (auto path = assets->GetPath()) { + const std::string overlay_path = path->data(); + if (IsFabricatedOverlay(overlay_path)) { + // FRRO don't have package name so we use the creating package here. + String8 frro_name = String8("FRRO"); + // Get the first part of it since the expected one should be like + // {overlayPackageName}-{overlayName}-{4 alphanumeric chars}.frro + // under /data/resource-cache/. + const std::string name = overlay_path.substr(overlay_path.rfind('/') + 1); + const size_t end = name.find('-'); + if (frro_name.size() != overlay_path.size() && end != std::string::npos) { + frro_name.append(base::StringPrintf(" created by %s", + name.substr(0 /* pos */, + end).c_str()).c_str()); + } + last_resolution_.best_package_name = frro_name; + } else { + last_resolution_.best_package_name = result->package_name->c_str(); } - last_resolution_.best_package_name = frro_name; - } else { - last_resolution_.best_package_name = result->package_name->c_str(); } + overlaid = true; } - overlaid = true; + continue; } - continue; - } - auto overlay_result = FindEntry(overlay_entry.GetResourceId(), density_override, - false /* stop_at_first_match */, - false /* ignore_configuration */); - if (UNLIKELY(IsIOError(overlay_result))) { - return base::unexpected(overlay_result.error()); - } - if (!overlay_result.has_value()) { - continue; - } + auto overlay_result = FindEntry(overlay_entry.GetResourceId(), density_override, + false /* stop_at_first_match */, + false /* ignore_configuration */); + if (UNLIKELY(IsIOError(overlay_result))) { + return base::unexpected(overlay_result.error()); + } + if (!overlay_result.has_value()) { + continue; + } - if (!overlay_result->config.isBetterThan(result->config, desired_config) - && overlay_result->config.compare(result->config) != 0) { - // The configuration of the entry for the overlay must be equal to or better than the target - // configuration to be chosen as the better value. - continue; - } + if (!overlay_result->config.isBetterThan(result->config, desired_config) + && overlay_result->config.compare(result->config) != 0) { + // The configuration of the entry for the overlay must be equal to or better than the target + // configuration to be chosen as the better value. + continue; + } - result->cookie = overlay_result->cookie; - result->entry = overlay_result->entry; - result->config = overlay_result->config; - result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); + result->cookie = overlay_result->cookie; + result->entry = overlay_result->entry; + result->config = overlay_result->config; + result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); - if (UNLIKELY(logging_enabled)) { - last_resolution_.steps.push_back( - Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->config.toString(), - overlay_result->cookie}); - last_resolution_.best_package_name = - overlay_result->package_name->c_str(); - overlaid = true; + if (UNLIKELY(logging_enabled)) { + last_resolution_.steps.push_back( + Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->config.toString(), + overlay_result->cookie}); + last_resolution_.best_package_name = + overlay_result->package_name->c_str(); + overlaid = true; + } } } } @@ -839,13 +898,7 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal( } void AssetManager2::ResetResourceResolution() const { - last_resolution_.cookie = kInvalidCookie; - last_resolution_.resid = 0; - last_resolution_.steps.clear(); - last_resolution_.type_string_ref = StringPoolRef(); - last_resolution_.entry_string_ref = StringPoolRef(); - last_resolution_.best_config_name.clear(); - last_resolution_.best_package_name.clear(); + last_resolution_ = Resolution{}; } void AssetManager2::SetResourceResolutionLoggingEnabled(bool enabled) { @@ -867,8 +920,12 @@ std::string AssetManager2::GetLastResourceResolution() const { return {}; } + auto op = StartOperation(); + const uint32_t resid = last_resolution_.resid; - const auto package = apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid)); + const auto& assets = GetApkAssets(cookie); + const auto package = + assets ? assets->GetLoadedArsc()->GetPackageById(get_package_id(resid)) : nullptr; std::string resource_name_string; if (package != nullptr) { @@ -898,8 +955,9 @@ std::string AssetManager2::GetLastResourceResolution() const { if (prefix == kStepStrings.end()) { continue; } - - log_stream << "\n\t" << prefix->second << ": " << apk_assets_[step.cookie]->GetDebugName(); + const auto& assets = GetApkAssets(step.cookie); + log_stream << "\n\t" << prefix->second << ": " + << (assets ? assets->GetDebugName() : "<null>") << " #" << step.cookie; if (!step.config_name.isEmpty()) { log_stream << " - " << step.config_name; } @@ -1429,6 +1487,37 @@ void AssetManager2::ForEachPackage(base::function_ref<bool(const std::string&, u } } +AssetManager2::ScopedOperation AssetManager2::StartOperation() const { + ++number_of_running_scoped_operations_; + return ScopedOperation(*this); +} + +void AssetManager2::FinishOperation() const { + if (number_of_running_scoped_operations_ < 1) { + ALOGW("Invalid FinishOperation() call when there's none happening"); + return; + } + if (--number_of_running_scoped_operations_ == 0) { + for (auto&& [_, assets] : apk_assets_) { + assets.clear(); + } + } +} + +const AssetManager2::ApkAssetsPtr& AssetManager2::GetApkAssets(ApkAssetsCookie cookie) const { + DCHECK(number_of_running_scoped_operations_ > 0) << "Must have an operation running"; + + if (cookie < 0 || cookie >= apk_assets_.size()) { + static const ApkAssetsPtr empty{}; + return empty; + } + auto& [wptr, res] = apk_assets_[cookie]; + if (!res) { + res = wptr.promote(); + } + return res; +} + Theme::Theme(AssetManager2* asset_manager) : asset_manager_(asset_manager) { } @@ -1561,14 +1650,16 @@ base::expected<std::monostate, IOError> Theme::SetTo(const Theme& source) { using SourceToDestinationRuntimePackageMap = std::unordered_map<int, int>; std::unordered_map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map; - // Determine which ApkAssets are loaded in both theme AssetManagers. - const auto& src_assets = source.asset_manager_->GetApkAssets(); - for (size_t i = 0; i < src_assets.size(); i++) { - const ApkAssets* src_asset = src_assets[i]; + auto op_src = source.asset_manager_->StartOperation(); + auto op_dst = asset_manager_->StartOperation(); - const auto& dest_assets = asset_manager_->GetApkAssets(); - for (size_t j = 0; j < dest_assets.size(); j++) { - const ApkAssets* dest_asset = dest_assets[j]; + for (size_t i = 0; i < source.asset_manager_->GetApkAssetsCount(); i++) { + const auto& src_asset = source.asset_manager_->GetApkAssets(i); + if (!src_asset) { + continue; + } + for (int j = 0; j < asset_manager_->GetApkAssetsCount(); j++) { + const auto& dest_asset = asset_manager_->GetApkAssets(j); if (src_asset != dest_asset) { // ResourcesManager caches and reuses ApkAssets when the same apk must be present in // multiple AssetManagers. Two ApkAssets point to the same version of the same resources @@ -1694,4 +1785,11 @@ void Theme::Dump() const { } } +AssetManager2::ScopedOperation::ScopedOperation(const AssetManager2& am) : am_(am) { +} + +AssetManager2::ScopedOperation::~ScopedOperation() { + am_.FinishOperation(); +} + } // namespace android diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp index c0fdfe25da21..fbfae5e2bcbe 100644 --- a/libs/androidfw/LoadedArsc.cpp +++ b/libs/androidfw/LoadedArsc.cpp @@ -323,7 +323,7 @@ LoadedPackage::GetEntryFromOffset(incfs::verified_map_ptr<ResTable_type> type_ch } base::expected<std::monostate, IOError> LoadedPackage::CollectConfigurations( - bool exclude_mipmap, std::set<ResTable_config>* out_configs) const {\ + bool exclude_mipmap, std::set<ResTable_config>* out_configs) const { for (const auto& type_spec : type_specs_) { if (exclude_mipmap) { const int type_idx = type_spec.first - 1; diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h index 6f88f41976cd..1fa67528c78b 100644 --- a/libs/androidfw/include/androidfw/ApkAssets.h +++ b/libs/androidfw/include/androidfw/ApkAssets.h @@ -17,12 +17,13 @@ #ifndef APKASSETS_H_ #define APKASSETS_H_ +#include <utils/RefBase.h> + #include <memory> #include <string> #include "android-base/macros.h" #include "android-base/unique_fd.h" - #include "androidfw/Asset.h" #include "androidfw/AssetsProvider.h" #include "androidfw/Idmap.h" @@ -31,34 +32,33 @@ namespace android { +class ApkAssets; + +using ApkAssetsPtr = sp<ApkAssets>; + // Holds an APK. -class ApkAssets { +class ApkAssets : public RefBase { public: // Creates an ApkAssets from a path on device. - static std::unique_ptr<ApkAssets> Load(const std::string& path, - package_property_t flags = 0U); + static ApkAssetsPtr Load(const std::string& path, package_property_t flags = 0U); // Creates an ApkAssets from an open file descriptor. - static std::unique_ptr<ApkAssets> LoadFromFd(base::unique_fd fd, - const std::string& debug_name, - package_property_t flags = 0U, - off64_t offset = 0, - off64_t len = AssetsProvider::kUnknownLength); + static ApkAssetsPtr LoadFromFd(base::unique_fd fd, const std::string& debug_name, + package_property_t flags = 0U, off64_t offset = 0, + off64_t len = AssetsProvider::kUnknownLength); // Creates an ApkAssets from an AssetProvider. // The ApkAssets will take care of destroying the AssetsProvider when it is destroyed. - static std::unique_ptr<ApkAssets> Load(std::unique_ptr<AssetsProvider> assets, - package_property_t flags = 0U); + static ApkAssetsPtr Load(std::unique_ptr<AssetsProvider> assets, package_property_t flags = 0U); // Creates an ApkAssets from the given asset file representing a resources.arsc. - static std::unique_ptr<ApkAssets> LoadTable(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, - package_property_t flags = 0U); + static ApkAssetsPtr LoadTable(std::unique_ptr<Asset> resources_asset, + std::unique_ptr<AssetsProvider> assets, + package_property_t flags = 0U); // Creates an ApkAssets from an IDMAP, which contains the original APK path, and the overlay // data. - static std::unique_ptr<ApkAssets> LoadOverlay(const std::string& idmap_path, - package_property_t flags = 0U); + static ApkAssetsPtr LoadOverlay(const std::string& idmap_path, package_property_t flags = 0U); // Path to the contents of the ApkAssets on disk. The path could represent an APk, a directory, // or some other file type. @@ -95,22 +95,27 @@ class ApkAssets { bool IsUpToDate() const; private: - static std::unique_ptr<ApkAssets> LoadImpl(std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap); - - static std::unique_ptr<ApkAssets> LoadImpl(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, - std::unique_ptr<LoadedIdmap> loaded_idmap); - - ApkAssets(std::unique_ptr<Asset> resources_asset, - std::unique_ptr<LoadedArsc> loaded_arsc, - std::unique_ptr<AssetsProvider> assets, - package_property_t property_flags, - std::unique_ptr<Asset> idmap_asset, + static ApkAssetsPtr LoadImpl(std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, + std::unique_ptr<LoadedIdmap> loaded_idmap); + + static ApkAssetsPtr LoadImpl(std::unique_ptr<Asset> resources_asset, + std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, + std::unique_ptr<Asset> idmap_asset, + std::unique_ptr<LoadedIdmap> loaded_idmap); + + // Allows us to make it possible to call make_shared from inside the class but still keeps the + // ctor 'private' for all means and purposes. + struct PrivateConstructorUtil { + explicit PrivateConstructorUtil() = default; + }; + + public: + ApkAssets(PrivateConstructorUtil, std::unique_ptr<Asset> resources_asset, + std::unique_ptr<LoadedArsc> loaded_arsc, std::unique_ptr<AssetsProvider> assets, + package_property_t property_flags, std::unique_ptr<Asset> idmap_asset, std::unique_ptr<LoadedIdmap> loaded_idmap); std::unique_ptr<Asset> resources_asset_; diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index f10cb9bf480a..fc391bc2ce67 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -17,14 +17,16 @@ #ifndef ANDROIDFW_ASSETMANAGER2_H_ #define ANDROIDFW_ASSETMANAGER2_H_ -#include "android-base/function_ref.h" -#include "android-base/macros.h" +#include <utils/RefBase.h> #include <array> #include <limits> #include <set> +#include <span> #include <unordered_map> +#include "android-base/function_ref.h" +#include "android-base/macros.h" #include "androidfw/ApkAssets.h" #include "androidfw/Asset.h" #include "androidfw/AssetManager.h" @@ -94,8 +96,25 @@ class AssetManager2 { size_t entry_len = 0u; }; - AssetManager2(); + using ApkAssetsPtr = sp<const ApkAssets>; + using ApkAssetsWPtr = wp<const ApkAssets>; + using ApkAssetsList = std::span<const ApkAssetsPtr>; + + AssetManager2() = default; explicit AssetManager2(AssetManager2&& other) = default; + AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration); + + struct ScopedOperation { + DISALLOW_COPY_AND_ASSIGN(ScopedOperation); + friend AssetManager2; + const AssetManager2& am_; + ScopedOperation(const AssetManager2& am); + + public: + ~ScopedOperation(); + }; + + [[nodiscard]] ScopedOperation StartOperation() const; // Sets/resets the underlying ApkAssets for this AssetManager. The ApkAssets // are not owned by the AssetManager, and must have a longer lifetime. @@ -103,10 +122,12 @@ class AssetManager2 { // Only pass invalidate_caches=false when it is known that the structure // change in ApkAssets is due to a safe addition of resources with completely // new resource IDs. - bool SetApkAssets(std::vector<const ApkAssets*> apk_assets, bool invalidate_caches = true); + bool SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches = true); + bool SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets, bool invalidate_caches = true); - inline const std::vector<const ApkAssets*>& GetApkAssets() const { - return apk_assets_; + const ApkAssetsPtr& GetApkAssets(ApkAssetsCookie cookie) const; + int GetApkAssetsCount() const { + return int(apk_assets_.size()); } // Returns the string pool for the given asset cookie. @@ -399,7 +420,7 @@ class AssetManager2 { // Assigns package IDs to all shared library ApkAssets. // Should be called whenever the ApkAssets are changed. - void BuildDynamicRefTable(); + void BuildDynamicRefTable(ApkAssetsList assets); // Purge all resources that are cached and vary by the configuration axis denoted by the // bitmask `diff`. @@ -410,16 +431,23 @@ class AssetManager2 { void RebuildFilterList(); // Retrieves the APK paths of overlays that overlay non-system packages. - std::set<const ApkAssets*> GetNonSystemOverlays() const; + std::set<ApkAssetsPtr> GetNonSystemOverlays() const; // AssetManager2::GetBag(resid) wraps this function to track which resource ids have already // been seen while traversing bag parents. base::expected<const ResolvedBag*, NullOrIOError> GetBag( uint32_t resid, std::vector<uint32_t>& child_resids) const; + // Finish an operation that was running with the current asset manager, and clean up the + // promoted apk assets when the last operation ends. + void FinishOperation() const; + // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must // have a longer lifetime. - std::vector<const ApkAssets*> apk_assets_; + // The second pair element is the promoted version of the assets, that is held for the duration + // of the currently running operation. FinishOperation() clears all promoted assets to make sure + // they can be released when the system needs that. + mutable std::vector<std::pair<ApkAssetsWPtr, ApkAssetsPtr>> apk_assets_; // DynamicRefTables for shared library package resolution. // These are ordered according to apk_assets_. The mappings may change depending on what is @@ -433,7 +461,7 @@ class AssetManager2 { // The current configuration set for this AssetManager. When this changes, cached resources // may need to be purged. - ResTable_config configuration_; + ResTable_config configuration_ = {}; // Cached set of bags. These are cached because they can inherit keys from parent bags, // which involves some calculation. @@ -446,6 +474,10 @@ class AssetManager2 { // Cached set of resolved resource values. mutable std::unordered_map<uint32_t, SelectedValue> cached_resolved_values_; + // Tracking the number of the started operations running with the current AssetManager. + // Finishing the last one clears all promoted apk assets. + mutable int number_of_running_scoped_operations_ = 0; + // Whether or not to save resource resolution steps bool resource_resolution_logging_enabled_ = false; diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h index 6fc6d64e2f6e..b6093dbb6d3d 100644 --- a/libs/androidfw/include/androidfw/MutexGuard.h +++ b/libs/androidfw/include/androidfw/MutexGuard.h @@ -14,12 +14,12 @@ * limitations under the License. */ -#ifndef ANDROIDFW_MUTEXGUARD_H -#define ANDROIDFW_MUTEXGUARD_H +#pragma once #include <mutex> #include <optional> #include <type_traits> +#include <utility> #include "android-base/macros.h" @@ -45,20 +45,25 @@ class ScopedLock; // template <typename T> class Guarded { - static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer"); + static_assert(!std::is_pointer_v<T>, "T must not be a raw pointer"); public: - Guarded() : guarded_(std::in_place, T()) { + Guarded() : guarded_(std::in_place) { } explicit Guarded(const T& guarded) : guarded_(std::in_place, guarded) { } - explicit Guarded(T&& guarded) : guarded_(std::in_place, std::forward<T>(guarded)) { + explicit Guarded(T&& guarded) : guarded_(std::in_place, std::move(guarded)) { } - ~Guarded() { - std::lock_guard<std::mutex> scoped_lock(lock_); + // Unfortunately, some legacy designs make even class deletion race-prone, where some other + // thread may have not finished working with the same object. For those cases one may destroy the + // object under a lock (but please fix your code, at least eventually!). + template <class Func> + void safeDelete(Func f) { + std::lock_guard scoped_lock(lock_); + f(guarded_ ? &guarded_.value() : nullptr); guarded_.reset(); } @@ -96,5 +101,3 @@ class ScopedLock { }; } // namespace android - -#endif // ANDROIDFW_MUTEXGUARD_H diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp index 19db25ce8811..70326b71da28 100644 --- a/libs/androidfw/tests/ApkAssets_test.cpp +++ b/libs/androidfw/tests/ApkAssets_test.cpp @@ -35,8 +35,7 @@ using ::testing::StrEq; namespace android { TEST(ApkAssetsTest, LoadApk) { - std::unique_ptr<const ApkAssets> loaded_apk = - ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); + auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); ASSERT_THAT(loaded_apk, NotNull()); const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc(); @@ -50,7 +49,7 @@ TEST(ApkAssetsTest, LoadApkFromFd) { unique_fd fd(::open(path.c_str(), O_RDONLY | O_BINARY)); ASSERT_THAT(fd.get(), Ge(0)); - std::unique_ptr<const ApkAssets> loaded_apk = ApkAssets::LoadFromFd(std::move(fd), path); + auto loaded_apk = ApkAssets::LoadFromFd(std::move(fd), path); ASSERT_THAT(loaded_apk, NotNull()); const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc(); @@ -60,8 +59,7 @@ TEST(ApkAssetsTest, LoadApkFromFd) { } TEST(ApkAssetsTest, LoadApkAsSharedLibrary) { - std::unique_ptr<const ApkAssets> loaded_apk = - ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk"); + auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk"); ASSERT_THAT(loaded_apk, NotNull()); const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc(); @@ -79,8 +77,7 @@ TEST(ApkAssetsTest, LoadApkAsSharedLibrary) { } TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) { - std::unique_ptr<const ApkAssets> loaded_apk = - ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); + auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); ASSERT_THAT(loaded_apk, NotNull()); { ASSERT_THAT(loaded_apk->GetAssetsProvider()->Open("res/layout/main.xml", @@ -91,8 +88,7 @@ TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) { } TEST(ApkAssetsTest, OpenUncompressedAssetFd) { - std::unique_ptr<const ApkAssets> loaded_apk = - ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); + auto loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); ASSERT_THAT(loaded_apk, NotNull()); auto asset = loaded_apk->GetAssetsProvider()->Open("assets/uncompressed.txt", diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp index c7ae618991b9..6fae72a6d10e 100644 --- a/libs/androidfw/tests/AssetManager2_bench.cpp +++ b/libs/androidfw/tests/AssetManager2_bench.cpp @@ -38,9 +38,9 @@ constexpr const static char* kFrameworkPath = "/system/framework/framework-res.a static void BM_AssetManagerLoadAssets(benchmark::State& state) { std::string path = GetTestDataPath() + "/basic/basic.apk"; while (state.KeepRunning()) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path); + auto apk = ApkAssets::Load(path); AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); } } BENCHMARK(BM_AssetManagerLoadAssets); @@ -61,9 +61,9 @@ BENCHMARK(BM_AssetManagerLoadAssetsOld); static void BM_AssetManagerLoadFrameworkAssets(benchmark::State& state) { std::string path = kFrameworkPath; while (state.KeepRunning()) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path); + auto apk = ApkAssets::Load(path); AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); } } BENCHMARK(BM_AssetManagerLoadFrameworkAssets); @@ -129,14 +129,14 @@ static void BM_AssetManagerGetResourceFrameworkLocaleOld(benchmark::State& state BENCHMARK(BM_AssetManagerGetResourceFrameworkLocaleOld); static void BM_AssetManagerGetBag(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); + auto apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); if (apk == nullptr) { state.SkipWithError("Failed to load assets"); return; } AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); while (state.KeepRunning()) { auto bag = assets.GetBag(app::R::style::StyleTwo); @@ -181,14 +181,14 @@ static void BM_AssetManagerGetBagOld(benchmark::State& state) { BENCHMARK(BM_AssetManagerGetBagOld); static void BM_AssetManagerGetResourceLocales(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath); + auto apk = ApkAssets::Load(kFrameworkPath); if (apk == nullptr) { state.SkipWithError("Failed to load assets"); return; } AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); while (state.KeepRunning()) { std::set<std::string> locales = @@ -217,14 +217,14 @@ static void BM_AssetManagerGetResourceLocalesOld(benchmark::State& state) { BENCHMARK(BM_AssetManagerGetResourceLocalesOld); static void BM_AssetManagerSetConfigurationFramework(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath); + auto apk = ApkAssets::Load(kFrameworkPath); if (apk == nullptr) { state.SkipWithError("Failed to load assets"); return; } AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); ResTable_config config; memset(&config, 0, sizeof(config)); diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp index 4394740e44ba..df3fa02ce44c 100644 --- a/libs/androidfw/tests/AssetManager2_test.cpp +++ b/libs/androidfw/tests/AssetManager2_test.cpp @@ -91,19 +91,19 @@ class AssetManager2Test : public ::testing::Test { } protected: - std::unique_ptr<const ApkAssets> basic_assets_; - std::unique_ptr<const ApkAssets> basic_de_fr_assets_; - std::unique_ptr<const ApkAssets> basic_xhdpi_assets_; - std::unique_ptr<const ApkAssets> basic_xxhdpi_assets_; - std::unique_ptr<const ApkAssets> style_assets_; - std::unique_ptr<const ApkAssets> lib_one_assets_; - std::unique_ptr<const ApkAssets> lib_two_assets_; - std::unique_ptr<const ApkAssets> libclient_assets_; - std::unique_ptr<const ApkAssets> appaslib_assets_; - std::unique_ptr<const ApkAssets> system_assets_; - std::unique_ptr<const ApkAssets> app_assets_; - std::unique_ptr<const ApkAssets> overlay_assets_; - std::unique_ptr<const ApkAssets> overlayable_assets_; + AssetManager2::ApkAssetsPtr basic_assets_; + AssetManager2::ApkAssetsPtr basic_de_fr_assets_; + AssetManager2::ApkAssetsPtr basic_xhdpi_assets_; + AssetManager2::ApkAssetsPtr basic_xxhdpi_assets_; + AssetManager2::ApkAssetsPtr style_assets_; + AssetManager2::ApkAssetsPtr lib_one_assets_; + AssetManager2::ApkAssetsPtr lib_two_assets_; + AssetManager2::ApkAssetsPtr libclient_assets_; + AssetManager2::ApkAssetsPtr appaslib_assets_; + AssetManager2::ApkAssetsPtr system_assets_; + AssetManager2::ApkAssetsPtr app_assets_; + AssetManager2::ApkAssetsPtr overlay_assets_; + AssetManager2::ApkAssetsPtr overlayable_assets_; }; TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) { @@ -114,7 +114,7 @@ TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) { AssetManager2 assetmanager; assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -138,7 +138,7 @@ TEST_F(AssetManager2Test, FindsResourceFromMultipleApkAssets) { AssetManager2 assetmanager; assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get(), basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -159,8 +159,7 @@ TEST_F(AssetManager2Test, FindsResourceFromSharedLibrary) { // libclient is built with lib_one and then lib_two in order. // Reverse the order to test that proper package ID re-assignment is happening. - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); auto value = assetmanager.GetResource(libclient::R::string::foo_one); ASSERT_TRUE(value.has_value()); @@ -195,7 +194,7 @@ TEST_F(AssetManager2Test, FindsResourceFromSharedLibrary) { TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({appaslib_assets_.get()}); + assetmanager.SetApkAssets({appaslib_assets_}); // The appaslib package will have been assigned the package ID 0x02. auto value = assetmanager.GetResource(fix_package_id(appaslib::R::integer::number1, 0x02)); @@ -206,27 +205,26 @@ TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) { TEST_F(AssetManager2Test, AssignsOverlayPackageIdLast) { AssetManager2 assetmanager; - assetmanager.SetApkAssets( - {overlayable_assets_.get(), overlay_assets_.get(), lib_one_assets_.get()}); + assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_}); - auto apk_assets = assetmanager.GetApkAssets(); - ASSERT_EQ(3, apk_assets.size()); - ASSERT_EQ(overlayable_assets_.get(), apk_assets[0]); - ASSERT_EQ(overlay_assets_.get(), apk_assets[1]); - ASSERT_EQ(lib_one_assets_.get(), apk_assets[2]); + ASSERT_EQ(3, assetmanager.GetApkAssetsCount()); + auto op = assetmanager.StartOperation(); + ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0)); + ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1)); + ASSERT_EQ(lib_one_assets_, assetmanager.GetApkAssets(2)); - auto get_first_package_id = [&assetmanager](const ApkAssets* apkAssets) -> uint8_t { + auto get_first_package_id = [&assetmanager](auto apkAssets) -> uint8_t { return assetmanager.GetAssignedPackageId(apkAssets->GetLoadedArsc()->GetPackages()[0].get()); }; - ASSERT_EQ(0x7f, get_first_package_id(overlayable_assets_.get())); - ASSERT_EQ(0x03, get_first_package_id(overlay_assets_.get())); - ASSERT_EQ(0x02, get_first_package_id(lib_one_assets_.get())); + ASSERT_EQ(0x7f, get_first_package_id(overlayable_assets_)); + ASSERT_EQ(0x03, get_first_package_id(overlay_assets_)); + ASSERT_EQ(0x02, get_first_package_id(lib_one_assets_)); } TEST_F(AssetManager2Test, GetSharedLibraryResourceName) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({lib_one_assets_.get()}); + assetmanager.SetApkAssets({lib_one_assets_}); auto name = assetmanager.GetResourceName(lib_one::R::string::foo); ASSERT_TRUE(name.has_value()); @@ -235,7 +233,7 @@ TEST_F(AssetManager2Test, GetSharedLibraryResourceName) { TEST_F(AssetManager2Test, GetResourceNameNonMatchingConfig) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({basic_de_fr_assets_}); auto value = assetmanager.GetResourceName(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -244,7 +242,7 @@ TEST_F(AssetManager2Test, GetResourceNameNonMatchingConfig) { TEST_F(AssetManager2Test, GetResourceTypeSpecFlags) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({basic_de_fr_assets_}); auto value = assetmanager.GetResourceTypeSpecFlags(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -253,7 +251,7 @@ TEST_F(AssetManager2Test, GetResourceTypeSpecFlags) { TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto bag = assetmanager.GetBag(basic::R::array::integerArray1); ASSERT_TRUE(bag.has_value()); @@ -280,8 +278,7 @@ TEST_F(AssetManager2Test, FindsBagResourceFromSharedLibrary) { // libclient is built with lib_one and then lib_two in order. // Reverse the order to test that proper package ID re-assignment is happening. - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); auto bag = assetmanager.GetBag(fix_package_id(lib_one::R::style::Theme, 0x03)); ASSERT_TRUE(bag.has_value()); @@ -300,8 +297,7 @@ TEST_F(AssetManager2Test, FindsBagResourceFromMultipleSharedLibraries) { // libclient is built with lib_one and then lib_two in order. // Reverse the order to test that proper package ID re-assignment is happening. - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); auto bag = assetmanager.GetBag(libclient::R::style::ThemeMultiLib); ASSERT_TRUE(bag.has_value()); @@ -321,8 +317,7 @@ TEST_F(AssetManager2Test, FindsStyleResourceWithParentFromSharedLibrary) { // libclient is built with lib_one and then lib_two in order. // Reverse the order to test that proper package ID re-assignment is happening. - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); auto bag = assetmanager.GetBag(libclient::R::style::Theme); ASSERT_TRUE(bag.has_value()); @@ -337,7 +332,7 @@ TEST_F(AssetManager2Test, FindsStyleResourceWithParentFromSharedLibrary) { TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); auto bag_one = assetmanager.GetBag(app::R::style::StyleOne); ASSERT_TRUE(bag_one.has_value()); @@ -401,7 +396,7 @@ TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) { TEST_F(AssetManager2Test, MergeStylesCircularDependency) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); // GetBag should stop traversing the parents of styles when a circular // dependency is detected @@ -412,7 +407,7 @@ TEST_F(AssetManager2Test, MergeStylesCircularDependency) { TEST_F(AssetManager2Test, ResolveReferenceToResource) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::integer::ref1); ASSERT_TRUE(value.has_value()); @@ -428,7 +423,7 @@ TEST_F(AssetManager2Test, ResolveReferenceToResource) { TEST_F(AssetManager2Test, ResolveReferenceToBag) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::integer::number2, true /*may_be_bag*/); ASSERT_TRUE(value.has_value()); @@ -444,7 +439,7 @@ TEST_F(AssetManager2Test, ResolveReferenceToBag) { TEST_F(AssetManager2Test, ResolveDeepIdReference) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); // Set up the resource ids auto high_ref = assetmanager.GetResourceId("@id/high_ref", "values", "com.android.basic"); @@ -470,8 +465,7 @@ TEST_F(AssetManager2Test, ResolveDeepIdReference) { TEST_F(AssetManager2Test, DensityOverride) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get(), basic_xhdpi_assets_.get(), - basic_xxhdpi_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_, basic_xhdpi_assets_, basic_xxhdpi_assets_}); assetmanager.SetConfiguration({ .density = ResTable_config::DENSITY_XHIGH, .sdkVersion = 21, @@ -493,7 +487,7 @@ TEST_F(AssetManager2Test, DensityOverride) { TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); // Create some kind of value that is NOT a reference. AssetManager2::SelectedValue value{}; @@ -509,7 +503,7 @@ TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) TEST_F(AssetManager2Test, ResolveReferenceMissingResourceDoNotCacheFlags) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); { AssetManager2::SelectedValue value{}; value.data = basic::R::string::test1; @@ -540,7 +534,7 @@ TEST_F(AssetManager2Test, ResolveReferenceMissingResourceDoNotCacheFlags) { TEST_F(AssetManager2Test, ResolveReferenceMissingResource) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); const uint32_t kMissingResId = 0x8001ffff; AssetManager2::SelectedValue value{}; @@ -558,7 +552,7 @@ TEST_F(AssetManager2Test, ResolveReferenceMissingResource) { TEST_F(AssetManager2Test, ResolveReferenceMissingResourceLib) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({libclient_assets_.get()}); + assetmanager.SetApkAssets({libclient_assets_}); AssetManager2::SelectedValue value{}; value.type = Res_value::TYPE_REFERENCE; @@ -580,7 +574,7 @@ static bool IsConfigurationPresent(const std::set<ResTable_config>& configuratio TEST_F(AssetManager2Test, GetResourceConfigurations) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({system_assets_, basic_de_fr_assets_}); auto configurations = assetmanager.GetResourceConfigurations(); ASSERT_TRUE(configurations.has_value()); @@ -625,7 +619,7 @@ TEST_F(AssetManager2Test, GetResourceConfigurations) { TEST_F(AssetManager2Test, GetResourceLocales) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({system_assets_, basic_de_fr_assets_}); std::set<std::string> locales = assetmanager.GetResourceLocales(); @@ -644,7 +638,7 @@ TEST_F(AssetManager2Test, GetResourceLocales) { TEST_F(AssetManager2Test, GetResourceId) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto resid = assetmanager.GetResourceId("com.android.basic:layout/main", "", ""); ASSERT_TRUE(resid.has_value()); @@ -661,7 +655,7 @@ TEST_F(AssetManager2Test, GetResourceId) { TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get()}); + assetmanager.SetApkAssets({system_assets_}); std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER); ASSERT_THAT(asset, NotNull()); @@ -673,7 +667,7 @@ TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) { TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()}); + assetmanager.SetApkAssets({system_assets_, app_assets_}); std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER); ASSERT_THAT(asset, NotNull()); @@ -685,7 +679,7 @@ TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) { TEST_F(AssetManager2Test, OpenDir) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get()}); + assetmanager.SetApkAssets({system_assets_}); std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir(""); ASSERT_THAT(asset_dir, NotNull()); @@ -707,7 +701,7 @@ TEST_F(AssetManager2Test, OpenDir) { TEST_F(AssetManager2Test, OpenDirFromManyApks) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()}); + assetmanager.SetApkAssets({system_assets_, app_assets_}); std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir(""); ASSERT_THAT(asset_dir, NotNull()); @@ -728,7 +722,7 @@ TEST_F(AssetManager2Test, GetLastPathWithoutEnablingReturnsEmpty) { AssetManager2 assetmanager; assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); assetmanager.SetResourceResolutionLoggingEnabled(false); auto value = assetmanager.GetResource(basic::R::string::test1); @@ -743,7 +737,7 @@ TEST_F(AssetManager2Test, GetLastPathWithoutResolutionReturnsEmpty) { AssetManager2 assetmanager; assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto result = assetmanager.GetLastResourceResolution(); EXPECT_EQ("", result); @@ -758,17 +752,18 @@ TEST_F(AssetManager2Test, GetLastPathWithSingleApkAssets) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); auto result = assetmanager.GetLastResourceResolution(); - EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n" - "\tFor config - de\n" - "\tFound initial: basic/basic.apk\n" - "Best matching is from default configuration of com.android.basic", - result); + EXPECT_EQ( + "Resolution for 0x7f030000 com.android.basic:string/test1\n" + "\tFor config - de\n" + "\tFound initial: basic/basic.apk #0\n" + "Best matching is from default configuration of com.android.basic", + result); } TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) { @@ -780,18 +775,19 @@ TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get(), basic_de_fr_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); auto result = assetmanager.GetLastResourceResolution(); - EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n" - "\tFor config - de\n" - "\tFound initial: basic/basic.apk\n" - "\tFound better: basic/basic_de_fr.apk - de\n" - "Best matching is from de configuration of com.android.basic", - result); + EXPECT_EQ( + "Resolution for 0x7f030000 com.android.basic:string/test1\n" + "\tFor config - de\n" + "\tFound initial: basic/basic.apk #0\n" + "\tFound better: basic/basic_de_fr.apk #1 - de\n" + "Best matching is from de configuration of com.android.basic", + result); } TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) { @@ -801,7 +797,7 @@ TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({basic_assets_.get()}); + assetmanager.SetApkAssets({basic_assets_}); auto value = assetmanager.GetResource(basic::R::string::test1); ASSERT_TRUE(value.has_value()); @@ -822,7 +818,7 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) { AssetManager2 assetmanager; assetmanager.SetResourceResolutionLoggingEnabled(true); assetmanager.SetConfiguration(desired_config); - assetmanager.SetApkAssets({overlayable_assets_.get()}); + assetmanager.SetApkAssets({overlayable_assets_}); const auto map = assetmanager.GetOverlayableMapForPackage(0x7f); ASSERT_NE(nullptr, map); @@ -838,4 +834,26 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) { std::string::npos); } +TEST_F(AssetManager2Test, GetApkAssets) { + AssetManager2 assetmanager; + assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_}); + + ASSERT_EQ(3, assetmanager.GetApkAssetsCount()); + EXPECT_EQ(1, overlayable_assets_->getStrongCount()); + EXPECT_EQ(1, overlay_assets_->getStrongCount()); + EXPECT_EQ(1, lib_one_assets_->getStrongCount()); + + { + auto op = assetmanager.StartOperation(); + ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0)); + ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1)); + EXPECT_EQ(2, overlayable_assets_->getStrongCount()); + EXPECT_EQ(2, overlay_assets_->getStrongCount()); + EXPECT_EQ(1, lib_one_assets_->getStrongCount()); + } + EXPECT_EQ(1, overlayable_assets_->getStrongCount()); + EXPECT_EQ(1, overlay_assets_->getStrongCount()); + EXPECT_EQ(1, lib_one_assets_->getStrongCount()); +} + } // namespace android diff --git a/libs/androidfw/tests/AttributeResolution_bench.cpp b/libs/androidfw/tests/AttributeResolution_bench.cpp index 1c89c61c8f78..384f4a78b36d 100644 --- a/libs/androidfw/tests/AttributeResolution_bench.cpp +++ b/libs/androidfw/tests/AttributeResolution_bench.cpp @@ -36,15 +36,14 @@ constexpr const static char* kFrameworkPath = "/system/framework/framework-res.a constexpr const static uint32_t Theme_Material_Light = 0x01030237u; static void BM_ApplyStyle(benchmark::State& state) { - std::unique_ptr<const ApkAssets> styles_apk = - ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); + auto styles_apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); if (styles_apk == nullptr) { state.SkipWithError("failed to load assets"); return; } AssetManager2 assetmanager; - assetmanager.SetApkAssets({styles_apk.get()}); + assetmanager.SetApkAssets({styles_apk}); std::unique_ptr<Asset> asset = assetmanager.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER); @@ -80,21 +79,20 @@ static void BM_ApplyStyle(benchmark::State& state) { BENCHMARK(BM_ApplyStyle); static void BM_ApplyStyleFramework(benchmark::State& state) { - std::unique_ptr<const ApkAssets> framework_apk = ApkAssets::Load(kFrameworkPath); + auto framework_apk = ApkAssets::Load(kFrameworkPath); if (framework_apk == nullptr) { state.SkipWithError("failed to load framework assets"); return; } - std::unique_ptr<const ApkAssets> basic_apk = - ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); + auto basic_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk"); if (basic_apk == nullptr) { state.SkipWithError("failed to load assets"); return; } AssetManager2 assetmanager; - assetmanager.SetApkAssets({framework_apk.get(), basic_apk.get()}); + assetmanager.SetApkAssets({framework_apk, basic_apk}); ResTable_config device_config; memset(&device_config, 0, sizeof(device_config)); diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp index bb9129ad01c8..329830fa47b2 100644 --- a/libs/androidfw/tests/AttributeResolution_test.cpp +++ b/libs/androidfw/tests/AttributeResolution_test.cpp @@ -36,11 +36,11 @@ class AttributeResolutionTest : public ::testing::Test { virtual void SetUp() override { styles_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); ASSERT_NE(nullptr, styles_assets_); - assetmanager_.SetApkAssets({styles_assets_.get()}); + assetmanager_.SetApkAssets({styles_assets_}); } protected: - std::unique_ptr<const ApkAssets> styles_assets_; + AssetManager2::ApkAssetsPtr styles_assets_; AssetManager2 assetmanager_; }; @@ -69,7 +69,7 @@ TEST(AttributeResolutionLibraryTest, ApplyStyleWithDefaultStyleResId) { AssetManager2 assetmanager; auto apk_assets = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk", PROPERTY_DYNAMIC); ASSERT_NE(nullptr, apk_assets); - assetmanager.SetApkAssets({apk_assets.get()}); + assetmanager.SetApkAssets({apk_assets}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp index 0fa0573bcbb8..b97dd96f8934 100644 --- a/libs/androidfw/tests/BenchmarkHelpers.cpp +++ b/libs/androidfw/tests/BenchmarkHelpers.cpp @@ -53,20 +53,18 @@ void GetResourceBenchmarkOld(const std::vector<std::string>& paths, const ResTab void GetResourceBenchmark(const std::vector<std::string>& paths, const ResTable_config* config, uint32_t resid, benchmark::State& state) { - std::vector<std::unique_ptr<const ApkAssets>> apk_assets; - std::vector<const ApkAssets*> apk_assets_ptrs; + std::vector<AssetManager2::ApkAssetsPtr> apk_assets; for (const std::string& path : paths) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path); + auto apk = ApkAssets::Load(path); if (apk == nullptr) { state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str()); return; } - apk_assets_ptrs.push_back(apk.get()); apk_assets.push_back(std::move(apk)); } AssetManager2 assetmanager; - assetmanager.SetApkAssets(apk_assets_ptrs); + assetmanager.SetApkAssets(apk_assets); if (config != nullptr) { assetmanager.SetConfiguration(*config); } diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp index b43491548e2b..60aa7d88925d 100644 --- a/libs/androidfw/tests/Idmap_test.cpp +++ b/libs/androidfw/tests/Idmap_test.cpp @@ -59,15 +59,16 @@ class IdmapTest : public ::testing::Test { protected: std::string original_path; - std::unique_ptr<const ApkAssets> system_assets_; - std::unique_ptr<const ApkAssets> overlay_assets_; - std::unique_ptr<const ApkAssets> overlayable_assets_; + AssetManager2::ApkAssetsPtr system_assets_; + AssetManager2::ApkAssetsPtr overlay_assets_; + AssetManager2::ApkAssetsPtr overlayable_assets_; }; std::string GetStringFromApkAssets(const AssetManager2& asset_manager, const AssetManager2::SelectedValue& value) { - auto assets = asset_manager.GetApkAssets(); - const ResStringPool* string_pool = assets[value.cookie]->GetLoadedArsc()->GetStringPool(); + auto op = asset_manager.StartOperation(); + const ResStringPool* string_pool = + asset_manager.GetApkAssets(value.cookie)->GetLoadedArsc()->GetStringPool(); return GetStringFromPool(string_pool, value.data); } @@ -75,8 +76,7 @@ std::string GetStringFromApkAssets(const AssetManager2& asset_manager, TEST_F(IdmapTest, OverlayOverridesResourceValue) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable5); ASSERT_TRUE(value.has_value()); @@ -87,8 +87,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValue) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable10); ASSERT_TRUE(value.has_value()); @@ -99,8 +98,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable8); ASSERT_TRUE(value.has_value()); @@ -111,8 +109,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::integer::config_integer); ASSERT_TRUE(value.has_value()); @@ -123,8 +120,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable11); ASSERT_TRUE(value.has_value()); @@ -135,8 +131,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) { TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable9); ASSERT_TRUE(value.has_value()); @@ -147,8 +142,7 @@ TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) { TEST_F(IdmapTest, OverlayOverridesXmlParser) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::layout::hello_view); ASSERT_TRUE(value.has_value()); @@ -186,8 +180,7 @@ TEST_F(IdmapTest, OverlayOverridesXmlParser) { TEST_F(IdmapTest, OverlaidResourceHasSameName) { AssetManager2 asset_manager; - asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({system_assets_, overlayable_assets_, overlay_assets_}); auto name = asset_manager.GetResourceName(overlayable::R::string::overlayable9); ASSERT_TRUE(name.has_value()); @@ -203,8 +196,7 @@ TEST_F(IdmapTest, OverlayLoaderInterop) { auto loader_assets = ApkAssets::LoadTable(std::move(asset), EmptyAssetsProvider::Create(), PROPERTY_LOADER); AssetManager2 asset_manager; - asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(), - overlay_assets_.get()}); + asset_manager.SetApkAssets({overlayable_assets_, loader_assets, overlay_assets_}); auto value = asset_manager.GetResource(overlayable::R::string::overlayable11); ASSERT_TRUE(value.has_value()); diff --git a/libs/androidfw/tests/Theme_bench.cpp b/libs/androidfw/tests/Theme_bench.cpp index f3d60bbe4f15..dfbb5a76dec6 100644 --- a/libs/androidfw/tests/Theme_bench.cpp +++ b/libs/androidfw/tests/Theme_bench.cpp @@ -28,14 +28,14 @@ constexpr const static uint32_t kStyleId = 0x01030237u; // android:style/Theme. constexpr const static uint32_t kAttrId = 0x01010030u; // android:attr/colorForeground static void BM_ThemeApplyStyleFramework(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath); + auto apk = ApkAssets::Load(kFrameworkPath); if (apk == nullptr) { state.SkipWithError("Failed to load assets"); return; } AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); while (state.KeepRunning()) { auto theme = assets.NewTheme(); @@ -62,10 +62,10 @@ static void BM_ThemeApplyStyleFrameworkOld(benchmark::State& state) { BENCHMARK(BM_ThemeApplyStyleFrameworkOld); static void BM_ThemeGetAttribute(benchmark::State& state) { - std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath); + auto apk = ApkAssets::Load(kFrameworkPath); AssetManager2 assets; - assets.SetApkAssets({apk.get()}); + assets.SetApkAssets({apk}); auto theme = assets.NewTheme(); theme->ApplyStyle(kStyleId, false /* force */); diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp index 77114f273d3d..e08a6a7f277d 100644 --- a/libs/androidfw/tests/Theme_test.cpp +++ b/libs/androidfw/tests/Theme_test.cpp @@ -53,16 +53,16 @@ class ThemeTest : public ::testing::Test { } protected: - std::unique_ptr<const ApkAssets> system_assets_; - std::unique_ptr<const ApkAssets> style_assets_; - std::unique_ptr<const ApkAssets> libclient_assets_; - std::unique_ptr<const ApkAssets> lib_one_assets_; - std::unique_ptr<const ApkAssets> lib_two_assets_; + AssetManager2::ApkAssetsPtr system_assets_; + AssetManager2::ApkAssetsPtr style_assets_; + AssetManager2::ApkAssetsPtr libclient_assets_; + AssetManager2::ApkAssetsPtr lib_one_assets_; + AssetManager2::ApkAssetsPtr lib_two_assets_; }; TEST_F(ThemeTest, EmptyTheme) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); EXPECT_EQ(0u, theme->GetChangingConfigurations()); @@ -72,7 +72,7 @@ TEST_F(ThemeTest, EmptyTheme) { TEST_F(ThemeTest, SingleThemeNoParent) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleOne).has_value()); @@ -92,7 +92,7 @@ TEST_F(ThemeTest, SingleThemeNoParent) { TEST_F(ThemeTest, SingleThemeWithParent) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value()); @@ -121,7 +121,7 @@ TEST_F(ThemeTest, SingleThemeWithParent) { TEST_F(ThemeTest, TryToUseBadResourceId) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value()); @@ -130,7 +130,7 @@ TEST_F(ThemeTest, TryToUseBadResourceId) { TEST_F(ThemeTest, MultipleThemesOverlaidNotForce) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value()); @@ -160,7 +160,7 @@ TEST_F(ThemeTest, MultipleThemesOverlaidNotForce) { TEST_F(ThemeTest, MultipleThemesOverlaidForced) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo).has_value()); @@ -190,8 +190,7 @@ TEST_F(ThemeTest, MultipleThemesOverlaidForced) { TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) { AssetManager2 assetmanager; - assetmanager.SetApkAssets( - {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); + assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_}); std::unique_ptr<Theme> theme = assetmanager.NewTheme(); ASSERT_TRUE(theme->ApplyStyle(libclient::R::style::Theme, false /*force*/).has_value()); @@ -216,7 +215,7 @@ TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) { TEST_F(ThemeTest, CopyThemeSameAssetManager) { AssetManager2 assetmanager; - assetmanager.SetApkAssets({style_assets_.get()}); + assetmanager.SetApkAssets({style_assets_}); std::unique_ptr<Theme> theme_one = assetmanager.NewTheme(); ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne).has_value()); @@ -253,10 +252,10 @@ TEST_F(ThemeTest, CopyThemeSameAssetManager) { TEST_F(ThemeTest, ThemeRebase) { AssetManager2 am; - am.SetApkAssets({style_assets_.get()}); + am.SetApkAssets({style_assets_}); AssetManager2 am_night; - am_night.SetApkAssets({style_assets_.get()}); + am_night.SetApkAssets({style_assets_}); ResTable_config night{}; night.uiMode = ResTable_config::UI_MODE_NIGHT_YES; @@ -327,12 +326,11 @@ TEST_F(ThemeTest, ThemeRebase) { TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) { AssetManager2 assetmanager_dst; - assetmanager_dst.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(), - libclient_assets_.get()}); + assetmanager_dst.SetApkAssets( + {system_assets_, lib_one_assets_, style_assets_, libclient_assets_}); AssetManager2 assetmanager_src; - assetmanager_src.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(), - style_assets_.get()}); + assetmanager_src.SetApkAssets({system_assets_, lib_two_assets_, lib_one_assets_, style_assets_}); auto theme_dst = assetmanager_dst.NewTheme(); ASSERT_TRUE(theme_dst->ApplyStyle(app::R::style::StyleOne).has_value()); @@ -376,10 +374,10 @@ TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) { TEST_F(ThemeTest, CopyNonReferencesWhenPackagesDiffer) { AssetManager2 assetmanager_dst; - assetmanager_dst.SetApkAssets({system_assets_.get()}); + assetmanager_dst.SetApkAssets({system_assets_}); AssetManager2 assetmanager_src; - assetmanager_src.SetApkAssets({system_assets_.get(), style_assets_.get()}); + assetmanager_src.SetApkAssets({system_assets_, style_assets_}); auto theme_dst = assetmanager_dst.NewTheme(); auto theme_src = assetmanager_src.NewTheme(); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 1a06b0184bc5..8d1169335d8d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1931,6 +1931,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mExternallyEnabled = enabled; if (!enabled && mShowing) { + if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) { + Log.d(TAG, "keyguardEnabled(false) overridden by user lockdown"); + return; + } // hiding keyguard that is showing, remember to reshow later if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, " + "disabling status bar expansion"); diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt index 6b993ce9e7bf..69f02f785b03 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt @@ -22,11 +22,13 @@ import android.app.Notification import android.app.Notification.EXTRA_SUBSTITUTE_APP_NAME import android.app.PendingIntent import android.app.StatusBarManager +import android.app.UriGrantsManager import android.app.smartspace.SmartspaceConfig import android.app.smartspace.SmartspaceManager import android.app.smartspace.SmartspaceSession import android.app.smartspace.SmartspaceTarget import android.content.BroadcastReceiver +import android.content.ContentProvider import android.content.ContentResolver import android.content.Context import android.content.Intent @@ -699,10 +701,13 @@ class MediaDataManager( Log.d(TAG, "adding track for $userId from browser: $desc") } + val currentEntry = mediaEntries.get(packageName) + val appUid = currentEntry?.appUid ?: Process.INVALID_UID + // Album art var artworkBitmap = desc.iconBitmap if (artworkBitmap == null && desc.iconUri != null) { - artworkBitmap = loadBitmapFromUri(desc.iconUri!!) + artworkBitmap = loadBitmapFromUriForUser(desc.iconUri!!, userId, appUid, packageName) } val artworkIcon = if (artworkBitmap != null) { @@ -711,9 +716,7 @@ class MediaDataManager( null } - val currentEntry = mediaEntries.get(packageName) val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() - val appUid = currentEntry?.appUid ?: Process.INVALID_UID val isExplicit = desc.extras?.getLong(MediaConstants.METADATA_KEY_IS_EXPLICIT) == MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT && @@ -1260,6 +1263,30 @@ class MediaDataManager( false } } + + /** Returns a bitmap if the user can access the given URI, else null */ + private fun loadBitmapFromUriForUser( + uri: Uri, + userId: Int, + appUid: Int, + packageName: String, + ): Bitmap? { + try { + val ugm = UriGrantsManager.getService() + ugm.checkGrantUriPermission_ignoreNonSystem( + appUid, + packageName, + ContentProvider.getUriWithoutUserId(uri), + Intent.FLAG_GRANT_READ_URI_PERMISSION, + ContentProvider.getUserIdFromUri(uri, userId) + ) + return loadBitmapFromUri(uri) + } catch (e: SecurityException) { + Log.e(TAG, "Failed to get URI permission: $e") + } + return null + } + /** * Load a bitmap from a URI * diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java index 9bc03336c3b0..7134f15d4fec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java @@ -48,6 +48,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; +import android.os.UserManager; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.transition.ChangeBounds; @@ -118,6 +119,8 @@ public class NotificationConversationInfo extends LinearLayout implements private NotificationGuts mGutsContainer; private OnConversationSettingsClickListener mOnConversationSettingsClickListener; + private UserManager mUm; + @VisibleForTesting boolean mSkipPost = false; private int mActualHeight; @@ -155,7 +158,9 @@ public class NotificationConversationInfo extends LinearLayout implements // People Tile add request. if (mSelectedAction == ACTION_FAVORITE && getPriority() != mSelectedAction) { mShadeController.animateCollapseShade(); - mPeopleSpaceWidgetManager.requestPinAppWidget(mShortcutInfo, new Bundle()); + if (mUm.isSameProfileGroup(UserHandle.USER_SYSTEM, mSbn.getNormalizedUserId())) { + mPeopleSpaceWidgetManager.requestPinAppWidget(mShortcutInfo, new Bundle()); + } } mGutsContainer.closeControls(v, /* save= */ true); }; @@ -188,6 +193,7 @@ public class NotificationConversationInfo extends LinearLayout implements public void bindNotification( ShortcutManager shortcutManager, PackageManager pm, + UserManager um, PeopleSpaceWidgetManager peopleSpaceWidgetManager, INotificationManager iNotificationManager, OnUserInteractionCallback onUserInteractionCallback, @@ -211,6 +217,7 @@ public class NotificationConversationInfo extends LinearLayout implements mEntry = entry; mSbn = entry.getSbn(); mPm = pm; + mUm = um; mAppName = mPackageName; mOnSettingsClickListener = onSettingsClick; mNotificationChannel = notificationChannel; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index 7dbca4276fcc..6f79ea8c543b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -30,6 +30,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.service.notification.StatusBarNotification; import android.util.ArraySet; @@ -112,6 +113,9 @@ public class NotificationGutsManager implements NotifGutsViewManager { private Runnable mOpenRunnable; private final INotificationManager mNotificationManager; private final PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; + + private final UserManager mUserManager; + private final LauncherApps mLauncherApps; private final ShortcutManager mShortcutManager; private final UserContextProvider mContextTracker; @@ -128,6 +132,7 @@ public class NotificationGutsManager implements NotifGutsViewManager { AccessibilityManager accessibilityManager, HighPriorityProvider highPriorityProvider, INotificationManager notificationManager, + UserManager userManager, PeopleSpaceWidgetManager peopleSpaceWidgetManager, LauncherApps launcherApps, ShortcutManager shortcutManager, @@ -150,6 +155,7 @@ public class NotificationGutsManager implements NotifGutsViewManager { mAccessibilityManager = accessibilityManager; mHighPriorityProvider = highPriorityProvider; mNotificationManager = notificationManager; + mUserManager = userManager; mPeopleSpaceWidgetManager = peopleSpaceWidgetManager; mLauncherApps = launcherApps; mShortcutManager = shortcutManager; @@ -471,6 +477,7 @@ public class NotificationGutsManager implements NotifGutsViewManager { notificationInfoView.bindNotification( mShortcutManager, pmUser, + mUserManager, mPeopleSpaceWidgetManager, mNotificationManager, mOnUserInteractionCallback, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 34ea91b94414..2247374dec50 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -157,8 +157,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock AuthController mAuthController; private @Mock ShadeExpansionStateManager mShadeExpansionStateManager; private @Mock ShadeWindowLogger mShadeWindowLogger; - private @Captor ArgumentCaptor<KeyguardUpdateMonitorCallback> - mKeyguardUpdateMonitorCallbackCaptor; private @Captor ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallback; private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake(); @@ -206,25 +204,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { } @Test - @TestableLooper.RunWithLooper(setAsMainLooper = true) - public void onLockdown_showKeyguard_evenIfKeyguardIsNotEnabledExternally() { - // GIVEN keyguard is not enabled and isn't showing - mViewMediator.onSystemReady(); - mViewMediator.setKeyguardEnabled(false); - TestableLooper.get(this).processAllMessages(); - captureKeyguardUpdateMonitorCallback(); - assertFalse(mViewMediator.isShowingAndNotOccluded()); - - // WHEN lockdown occurs - when(mLockPatternUtils.isUserInLockdown(anyInt())).thenReturn(true); - mKeyguardUpdateMonitorCallbackCaptor.getValue().onStrongAuthStateChanged(0); - - // THEN keyguard is shown - TestableLooper.get(this).processAllMessages(); - assertTrue(mViewMediator.isShowingAndNotOccluded()); - } - - @Test public void testOnGoingToSleep_UpdatesKeyguardGoingAway() { mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER); verify(mUpdateMonitor).dispatchKeyguardGoingAway(false); @@ -829,10 +808,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null); } - private void captureKeyguardUpdateMonitorCallback() { - verify(mUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallbackCaptor.capture()); - } - private void captureKeyguardStateControllerCallback() { verify(mKeyguardStateController).addCallback(mKeyguardStateControllerCallback.capture()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt index 56698e0ec41c..9a415f571bd5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt @@ -16,10 +16,12 @@ package com.android.systemui.media.controls.pipeline +import android.app.IUriGrantsManager import android.app.Notification import android.app.Notification.FLAG_NO_CLEAR import android.app.Notification.MediaStyle import android.app.PendingIntent +import android.app.UriGrantsManager import android.app.smartspace.SmartspaceAction import android.app.smartspace.SmartspaceConfig import android.app.smartspace.SmartspaceManager @@ -27,12 +29,14 @@ import android.app.smartspace.SmartspaceTarget import android.content.Intent import android.content.pm.PackageManager import android.graphics.Bitmap +import android.graphics.ImageDecoder import android.graphics.drawable.Icon import android.media.MediaDescription import android.media.MediaMetadata import android.media.session.MediaController import android.media.session.MediaSession import android.media.session.PlaybackState +import android.net.Uri import android.os.Bundle import android.provider.Settings import android.service.notification.StatusBarNotification @@ -40,6 +44,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import androidx.media.utils.MediaConstants import androidx.test.filters.SmallTest +import com.android.dx.mockito.inline.extended.ExtendedMockito import com.android.internal.logging.InstanceId import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.InstanceIdSequenceFake @@ -83,7 +88,9 @@ import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoSession import org.mockito.junit.MockitoJUnit +import org.mockito.quality.Strictness private const val KEY = "KEY" private const val KEY_2 = "KEY_2" @@ -149,6 +156,8 @@ class MediaDataManagerTest : SysuiTestCase() { @Captor lateinit var stateCallbackCaptor: ArgumentCaptor<(String, PlaybackState) -> Unit> @Captor lateinit var sessionCallbackCaptor: ArgumentCaptor<(String) -> Unit> @Captor lateinit var smartSpaceConfigBuilderCaptor: ArgumentCaptor<SmartspaceConfig> + @Mock private lateinit var ugm: IUriGrantsManager + @Mock private lateinit var imageSource: ImageDecoder.Source private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20) @@ -159,8 +168,17 @@ class MediaDataManagerTest : SysuiTestCase() { 1 ) + private lateinit var staticMockSession: MockitoSession + @Before fun setup() { + staticMockSession = + ExtendedMockito.mockitoSession() + .mockStatic<UriGrantsManager>(UriGrantsManager::class.java) + .mockStatic<ImageDecoder>(ImageDecoder::class.java) + .strictness(Strictness.LENIENT) + .startMocking() + whenever(UriGrantsManager.getService()).thenReturn(ugm) foregroundExecutor = FakeExecutor(clock) backgroundExecutor = FakeExecutor(clock) uiExecutor = FakeExecutor(clock) @@ -271,6 +289,7 @@ class MediaDataManagerTest : SysuiTestCase() { @After fun tearDown() { + staticMockSession.finishMocking() session.release() mediaDataManager.destroy() Settings.Secure.putInt( @@ -2199,6 +2218,66 @@ class MediaDataManagerTest : SysuiTestCase() { verify(listener).onMediaDataRemoved(eq(KEY)) } + @Test + fun testResumeMediaLoaded_hasArtPermission_artLoaded() { + // When resume media is loaded and user/app has permission to access the art URI, + whenever( + ugm.checkGrantUriPermission_ignoreNonSystem( + anyInt(), + any(), + any(), + anyInt(), + anyInt() + ) + ) + .thenReturn(1) + val artwork = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) + val uri = Uri.parse("content://example") + whenever(ImageDecoder.createSource(any(), eq(uri))).thenReturn(imageSource) + whenever(ImageDecoder.decodeBitmap(any(), any())).thenReturn(artwork) + + val desc = + MediaDescription.Builder().run { + setTitle(SESSION_TITLE) + setIconUri(uri) + build() + } + addResumeControlAndLoad(desc) + + // Then the artwork is loaded + assertThat(mediaDataCaptor.value.artwork).isNotNull() + } + + @Test + fun testResumeMediaLoaded_noArtPermission_noArtLoaded() { + // When resume media is loaded and user/app does not have permission to access the art URI + whenever( + ugm.checkGrantUriPermission_ignoreNonSystem( + anyInt(), + any(), + any(), + anyInt(), + anyInt() + ) + ) + .thenThrow(SecurityException("Test no permission")) + val artwork = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) + val uri = Uri.parse("content://example") + whenever(ImageDecoder.createSource(any(), eq(uri))).thenReturn(imageSource) + whenever(ImageDecoder.decodeBitmap(any(), any())).thenReturn(artwork) + + val desc = + MediaDescription.Builder().run { + setTitle(SESSION_TITLE) + setIconUri(uri) + build() + } + addResumeControlAndLoad(desc) + + // Then the artwork is not loaded + assertThat(mediaDataCaptor.value.artwork).isNull() + } + /** Helper function to add a basic media notification and capture the resulting MediaData */ private fun addNotificationAndLoad() { addNotificationAndLoad(mediaNotification) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java index 90adabfadd5d..596e9a2613d7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java @@ -62,6 +62,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.os.Handler; import android.os.UserHandle; +import android.os.UserManager; import android.service.notification.StatusBarNotification; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; @@ -132,6 +133,8 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Mock private PackageManager mMockPackageManager; @Mock + private UserManager mUserManager; + @Mock private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private BubblesManager mBubblesManager; @@ -238,6 +241,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -262,6 +266,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -314,6 +319,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -339,6 +345,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -363,6 +370,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -398,6 +406,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -423,6 +432,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -452,6 +462,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -476,6 +487,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -504,6 +516,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -532,6 +545,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -563,6 +577,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -600,6 +615,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -628,6 +644,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -663,6 +680,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -691,6 +709,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -735,6 +754,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -778,6 +798,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -822,6 +843,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -860,6 +882,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -896,6 +919,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -936,6 +960,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -967,6 +992,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -996,6 +1022,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -1033,6 +1060,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -1069,6 +1097,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -1104,6 +1133,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -1143,6 +1173,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -1173,6 +1204,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -1198,6 +1230,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -1219,11 +1252,13 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Test public void testSelectPriorityRequestsPinPeopleTile() { + when(mUserManager.isSameProfileGroup(anyInt(), anyInt())).thenReturn(true); //WHEN channel is default importance mNotificationChannel.setImportantConversation(false); mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -1250,10 +1285,45 @@ public class NotificationConversationInfoTest extends SysuiTestCase { } @Test + public void testSelectPriorityRequestsPinPeopleTile_noMultiuser() { + when(mUserManager.isSameProfileGroup(anyInt(), anyInt())).thenReturn(false); + //WHEN channel is default importance + mNotificationChannel.setImportantConversation(false); + mNotificationInfo.bindNotification( + mShortcutManager, + mMockPackageManager, + mUserManager, + mPeopleSpaceWidgetManager, + mMockINotificationManager, + mOnUserInteractionCallback, + TEST_PACKAGE_NAME, + mNotificationChannel, + mEntry, + mBubbleMetadata, + null, + mIconFactory, + mContext, + true, + mTestHandler, + mTestHandler, null, Optional.of(mBubblesManager), + mShadeController); + + // WHEN user clicks "priority" + mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE); + + // and then done + mNotificationInfo.findViewById(R.id.done).performClick(); + + // No widget prompt; on a secondary user + verify(mPeopleSpaceWidgetManager, never()).requestPinAppWidget(any(), any()); + } + + @Test public void testSelectDefaultDoesNotRequestPinPeopleTile() { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, @@ -1288,6 +1358,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mNotificationInfo.bindNotification( mShortcutManager, mMockPackageManager, + mUserManager, mPeopleSpaceWidgetManager, mMockINotificationManager, mOnUserInteractionCallback, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java index 3cefc9973d09..705d52bcf13f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java @@ -52,6 +52,7 @@ import android.content.pm.ShortcutManager; import android.graphics.Color; import android.os.Binder; import android.os.Handler; +import android.os.UserManager; import android.provider.Settings; import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; @@ -137,6 +138,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase { @Mock private HeadsUpManagerPhone mHeadsUpManagerPhone; @Mock private ActivityStarter mActivityStarter; + @Mock private UserManager mUserManager; + @Before public void setUp() { mTestableLooper = TestableLooper.get(this); @@ -147,7 +150,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { mGutsManager = new NotificationGutsManager(mContext, mHandler, mHandler, mAccessibilityManager, - mHighPriorityProvider, mINotificationManager, + mHighPriorityProvider, mINotificationManager, mUserManager, mPeopleSpaceWidgetManager, mLauncherApps, mShortcutManager, mChannelEditorDialogController, mContextTracker, mAssistantFeedbackController, Optional.of(mBubblesManager), new UiEventLoggerFake(), mOnUserInteractionCallback, diff --git a/rs/jni/Android.bp b/rs/jni/Android.bp index 8a6897c055c5..f732c216c250 100644 --- a/rs/jni/Android.bp +++ b/rs/jni/Android.bp @@ -22,6 +22,7 @@ package { cc_library_shared { name: "librs_jni", + cpp_std: "gnu++2b", srcs: ["android_renderscript_RenderScript.cpp"], shared_libs: [ diff --git a/services/core/java/com/android/server/PendingIntentUtils.java b/services/core/java/com/android/server/PendingIntentUtils.java index 1600101b20f4..a72a4d254a2a 100644 --- a/services/core/java/com/android/server/PendingIntentUtils.java +++ b/services/core/java/com/android/server/PendingIntentUtils.java @@ -34,6 +34,7 @@ public class PendingIntentUtils { public static Bundle createDontSendToRestrictedAppsBundle(@Nullable Bundle bundle) { final BroadcastOptions options = BroadcastOptions.makeBasic(); options.setDontSendToRestrictedApps(true); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); if (bundle == null) { return options.toBundle(); } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index c30b522f6ac7..8e1e3d86146f 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -4984,7 +4984,7 @@ public class AccountManagerService p.setDataPosition(0); Bundle simulateBundle = p.readBundle(); p.recycle(); - Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT); + Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class); if (intent != null && intent.getClass() != Intent.class) { return false; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 8089dcfe7ebc..638e3946c8f9 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9694,6 +9694,13 @@ public class ActivityManagerService extends IActivityManager.Stub public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) { + final int callingUid = Binder.getCallingUid(); + if (callingUid != ROOT_UID && callingUid != Process.SHELL_UID) { + if (resultReceiver != null) { + resultReceiver.send(-1, null); + } + throw new SecurityException("Shell commands are only callable by root or shell"); + } (new ActivityManagerShellCommand(this, false)).exec( this, in, out, err, args, callback, resultReceiver); } diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index 28cb7f0b03a6..8456927b2cdf 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -376,6 +376,7 @@ class ShortcutPackage extends ShortcutPackageItem { // Extract Icon and update the icon res ID and the bitmap path. s.saveIconAndFixUpShortcutLocked(this, newShortcut); s.fixUpShortcutResourceNamesAndValues(newShortcut); + ensureShortcutCountBeforePush(); saveShortcut(newShortcut); } @@ -430,7 +431,6 @@ class ShortcutPackage extends ShortcutPackageItem { @NonNull List<ShortcutInfo> changedShortcuts) { Preconditions.checkArgument(newShortcut.isEnabled(), "pushDynamicShortcuts() cannot publish disabled shortcuts"); - ensureShortcutCountBeforePush(); newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC); diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 5b3514c01f9f..365f332aff29 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -15,6 +15,7 @@ */ package com.android.server.pm; +import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED; import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI; import android.Manifest.permission; @@ -24,6 +25,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; +import android.app.ActivityOptions; import android.app.AppGlobals; import android.app.IUidObserver; import android.app.IUriGrantsManager; @@ -35,6 +37,7 @@ import android.app.usage.UsageStatsManagerInternal; import android.appwidget.AppWidgetProviderInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; +import android.content.ContentProvider; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -1740,6 +1743,10 @@ public class ShortcutService extends IShortcutService.Stub { android.util.EventLog.writeEvent(0x534e4554, "109824443", -1, ""); throw new SecurityException("Shortcut package name mismatch"); } + final int callingUid = injectBinderCallingUid(); + if (UserHandle.getUserId(callingUid) != si.getUserId()) { + throw new SecurityException("User-ID in shortcut doesn't match the caller"); + } } private void verifyShortcutInfoPackages( @@ -1925,11 +1932,32 @@ public class ShortcutService extends IShortcutService.Stub { } if (shortcut.getIcon() != null) { ShortcutInfo.validateIcon(shortcut.getIcon()); + validateIconURI(shortcut); } shortcut.replaceFlags(shortcut.getFlags() & ShortcutInfo.FLAG_LONG_LIVED); } + // Validates the calling process has permission to access shortcut icon's image uri + private void validateIconURI(@NonNull final ShortcutInfo si) { + final int callingUid = injectBinderCallingUid(); + final Icon icon = si.getIcon(); + if (icon == null) { + // There's no icon in this shortcut, nothing to validate here. + return; + } + int iconType = icon.getType(); + if (iconType != Icon.TYPE_URI && iconType != Icon.TYPE_URI_ADAPTIVE_BITMAP) { + // The icon is not URI-based, nothing to validate. + return; + } + final Uri uri = icon.getUri(); + mUriGrantsManagerInternal.checkGrantUriPermission(callingUid, si.getPackage(), + ContentProvider.getUriWithoutUserId(uri), + Intent.FLAG_GRANT_READ_URI_PERMISSION, + ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(callingUid))); + } + private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) { fixUpIncomingShortcutInfo(shortcut, forUpdate, /*forPinRequest=*/ false); } @@ -4407,8 +4435,11 @@ public class ShortcutService extends IShortcutService.Stub { return; } try { + ActivityOptions options = ActivityOptions.makeBasic() + .setPendingIntentBackgroundActivityStartMode( + MODE_BACKGROUND_ACTIVITY_START_DENIED); intentSender.sendIntent(mContext, /* code= */ 0, extras, - /* onFinished=*/ null, /* handler= */ null); + /* onFinished=*/ null, /* handler= */ null, null, options.toBundle()); } catch (SendIntentException e) { Slog.w(TAG, "sendIntent failed().", e); } diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index 01fdc8800c0e..1faba099a547 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -41,6 +41,7 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppGlobals; @@ -62,6 +63,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -1304,6 +1306,46 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub implements return false; } + /** + * Check if the targetPkg can be granted permission to access uri by + * the callingUid using the given modeFlags. See {@link #checkGrantUriPermissionUnlocked}. + * + * @param callingUid The uid of the grantor app that has permissions to the uri. + * @param targetPkg The package name of the granted app that needs permissions to the uri. + * @param uri The uri for which permissions should be granted. + * @param modeFlags The modes to grant. See {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}, etc. + * @param userId The userId in which the uri is to be resolved. + * @return uid of the target or -1 if permission grant not required. Returns -1 if the caller + * does not hold INTERACT_ACROSS_USERS_FULL + * @throws SecurityException if the grant is not allowed. + */ + @Override + @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) + public int checkGrantUriPermission_ignoreNonSystem(int callingUid, String targetPkg, Uri uri, + int modeFlags, int userId) { + if (!isCallerIsSystemOrPrivileged()) { + return Process.INVALID_UID; + } + final long origId = Binder.clearCallingIdentity(); + try { + return checkGrantUriPermissionUnlocked(callingUid, targetPkg, uri, modeFlags, + userId); + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + private boolean isCallerIsSystemOrPrivileged() { + final int uid = Binder.getCallingUid(); + if (uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) { + return true; + } + return ActivityManager.checkComponentPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + uid, /* owningUid = */-1, /* exported = */ true) + == PackageManager.PERMISSION_GRANTED; + } + @Override public ArrayList<UriPermission> providePersistentUriGrants() { final ArrayList<UriPermission> result = new ArrayList<>(); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 47b51ac164b9..6b65922c198e 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.Manifest.permission.BIND_VOICE_INTERACTION; import static android.Manifest.permission.CHANGE_CONFIGURATION; +import static android.Manifest.permission.CONTROL_KEYGUARD; import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; import static android.Manifest.permission.DETECT_SCREEN_CAPTURE; import static android.Manifest.permission.INTERACT_ACROSS_USERS; @@ -3545,6 +3546,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void keyguardGoingAway(int flags) { + mAmInternal.enforceCallingPermission(CONTROL_KEYGUARD, "unlock keyguard"); enforceNotIsolatedCaller("keyguardGoingAway"); final long token = Binder.clearCallingIdentity(); try { diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java index 272452e1b2ae..6589503c9748 100644 --- a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java +++ b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java @@ -32,6 +32,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.ResultReceiver; +import android.os.UserHandle; import android.service.credentials.CredentialProviderInfoFactory; import android.util.Slog; @@ -171,7 +172,9 @@ public class CredentialManagerUi { .setAction(UUID.randomUUID().toString()); //TODO: Create unique pending intent using request code and cancel any pre-existing pending // intents - return PendingIntent.getActivity( - mContext, /*requestCode=*/0, intent, PendingIntent.FLAG_IMMUTABLE); + return PendingIntent.getActivityAsUser( + mContext, /*requestCode=*/0, intent, + PendingIntent.FLAG_IMMUTABLE, /*options=*/null, + UserHandle.of(mUserId)); } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 51e4fe3027f3..23a1d4e0b37b 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -16646,16 +16646,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public PackagePolicy getCredentialManagerPolicy() { + public PackagePolicy getCredentialManagerPolicy(int userId) { if (!mHasFeature) { return null; } final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization( canWriteCredentialManagerPolicy(caller) || canQueryAdminPolicy(caller)); + if (userId != caller.getUserId()) { + Preconditions.checkCallAuthorization( + hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS)); + } synchronized (getLockObject()) { - ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(userId); return (admin != null) ? admin.mCredentialManagerPolicy : null; } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 72c9791a3ceb..86d2b2fc6b56 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -5903,6 +5903,49 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testVisitUris_styleExtrasWithoutStyle() { + Notification notification = new Notification.Builder(mContext, "a") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .build(); + + Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle( + personWithIcon("content://user")) + .addHistoricMessage(new Notification.MessagingStyle.Message("Heyhey!", + System.currentTimeMillis(), + personWithIcon("content://historicalMessenger"))) + .addMessage(new Notification.MessagingStyle.Message("Are you there", + System.currentTimeMillis(), + personWithIcon("content://messenger"))) + .setShortcutIcon( + Icon.createWithContentUri("content://conversationShortcut")); + messagingStyle.addExtras(notification.extras); // Instead of Builder.setStyle(style). + + Notification.CallStyle callStyle = Notification.CallStyle.forOngoingCall( + personWithIcon("content://caller"), + PendingIntent.getActivity(mContext, 0, new Intent(), + PendingIntent.FLAG_IMMUTABLE)) + .setVerificationIcon(Icon.createWithContentUri("content://callVerification")); + callStyle.addExtras(notification.extras); // Same. + + Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); + notification.visitUris(visitor); + + verify(visitor).accept(eq(Uri.parse("content://user"))); + verify(visitor).accept(eq(Uri.parse("content://historicalMessenger"))); + verify(visitor).accept(eq(Uri.parse("content://messenger"))); + verify(visitor).accept(eq(Uri.parse("content://conversationShortcut"))); + verify(visitor).accept(eq(Uri.parse("content://caller"))); + verify(visitor).accept(eq(Uri.parse("content://callVerification"))); + } + + private static Person personWithIcon(String iconUri) { + return new Person.Builder() + .setName("Mr " + iconUri) + .setIcon(Icon.createWithContentUri(iconUri)) + .build(); + } + + @Test public void testVisitUris_wearableExtender() { Icon actionIcon = Icon.createWithContentUri("content://media/action"); Icon wearActionIcon = Icon.createWithContentUri("content://media/wearAction"); diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp index 90239212f665..e17209088750 100644 --- a/startop/view_compiler/Android.bp +++ b/startop/view_compiler/Android.bp @@ -40,7 +40,7 @@ cc_defaults { "libziparchive", "libz", ], - cppflags: ["-std=c++17"], + cpp_std: "gnu++2b", target: { android: { shared_libs: [ @@ -80,7 +80,7 @@ cc_binary { "libgflags", "libviewcompiler", ], - host_supported: true + host_supported: true, } cc_test_host { diff --git a/startop/view_compiler/apk_layout_compiler.cc b/startop/view_compiler/apk_layout_compiler.cc index 1d3b648175cc..5f5652c2acac 100644 --- a/startop/view_compiler/apk_layout_compiler.cc +++ b/startop/view_compiler/apk_layout_compiler.cc @@ -80,10 +80,10 @@ bool CanCompileLayout(ResXMLParser* parser) { } namespace { -void CompileApkAssetsLayouts(const std::unique_ptr<android::ApkAssets>& assets, - CompilationTarget target, std::ostream& target_out) { +void CompileApkAssetsLayouts(const android::ApkAssetsPtr& assets, CompilationTarget target, + std::ostream& target_out) { android::AssetManager2 resources; - resources.SetApkAssets({assets.get()}); + resources.SetApkAssets({assets}); std::string package_name; diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp index 28fcc1a4800e..725a1b86f616 100644 --- a/tools/aapt2/cmd/Link_test.cpp +++ b/tools/aapt2/cmd/Link_test.cpp @@ -575,7 +575,7 @@ TEST_F(LinkTest, StagedAndroidApi) { android::AssetManager2 am; auto android_asset = android::ApkAssets::Load(android_apk); ASSERT_THAT(android_asset, NotNull()); - ASSERT_TRUE(am.SetApkAssets({android_asset.get()})); + ASSERT_TRUE(am.SetApkAssets({android_asset})); auto result = am.GetResourceId("android:attr/finalized_res"); ASSERT_TRUE(result.has_value()); @@ -631,7 +631,7 @@ TEST_F(LinkTest, FinalizedAndroidApi) { auto app_against_non_final = android::ApkAssets::Load(app_apk); ASSERT_THAT(android_asset, NotNull()); ASSERT_THAT(app_against_non_final, NotNull()); - ASSERT_TRUE(am.SetApkAssets({android_asset.get(), app_against_non_final.get()})); + ASSERT_TRUE(am.SetApkAssets({android_asset, app_against_non_final})); auto result = am.GetResourceId("android:attr/finalized_res"); ASSERT_TRUE(result.has_value()); @@ -667,7 +667,7 @@ TEST_F(LinkTest, FinalizedAndroidApi) { auto app_against_final = android::ApkAssets::Load(app_apk_respin); ASSERT_THAT(app_against_final, NotNull()); - ASSERT_TRUE(am.SetApkAssets({android_asset.get(), app_against_final.get()})); + ASSERT_TRUE(am.SetApkAssets({android_asset, app_against_final})); { auto style = am.GetBag(0x7f020000); diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp index bca62da447b0..d78baf9ffeb4 100644 --- a/tools/aapt2/process/SymbolTable.cpp +++ b/tools/aapt2/process/SymbolTable.cpp @@ -220,15 +220,9 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName( bool AssetManagerSymbolSource::AddAssetPath(StringPiece path) { TRACE_CALL(); - if (std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path.data())) { + if (auto apk = ApkAssets::Load(path.data())) { apk_assets_.push_back(std::move(apk)); - - std::vector<const ApkAssets*> apk_assets; - for (const std::unique_ptr<const ApkAssets>& apk_asset : apk_assets_) { - apk_assets.push_back(apk_asset.get()); - } - - asset_manager_.SetApkAssets(apk_assets); + asset_manager_.SetApkAssets(apk_assets_); return true; } return false; @@ -251,7 +245,7 @@ bool AssetManagerSymbolSource::IsPackageDynamic(uint32_t packageId, return true; } - for (const std::unique_ptr<const ApkAssets>& assets : apk_assets_) { + for (auto&& assets : apk_assets_) { for (const std::unique_ptr<const android::LoadedPackage>& loaded_package : assets->GetLoadedArsc()->GetPackages()) { if (package_name == loaded_package->GetPackageName() && loaded_package->IsDynamic()) { @@ -266,10 +260,11 @@ bool AssetManagerSymbolSource::IsPackageDynamic(uint32_t packageId, static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable( android::AssetManager2& am, ResourceId id) { using namespace android; - if (am.GetApkAssets().empty()) { + if (am.GetApkAssetsCount() == 0) { return {}; } + auto op = am.StartOperation(); auto bag_result = am.GetBag(id.id); if (!bag_result.has_value()) { return nullptr; diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h index b09ff702ca58..36eb0bab6046 100644 --- a/tools/aapt2/process/SymbolTable.h +++ b/tools/aapt2/process/SymbolTable.h @@ -207,8 +207,8 @@ class AssetManagerSymbolSource : public ISymbolSource { } private: + std::vector<android::AssetManager2::ApkAssetsPtr> apk_assets_; android::AssetManager2 asset_manager_; - std::vector<std::unique_ptr<const android::ApkAssets>> apk_assets_; DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource); }; |