diff options
author | MÃ¥rten Kongstad <marten.kongstad@volvocars.com> | 2021-05-10 11:00:17 +0000 |
---|---|---|
committer | Ryan Mitchell <rtmitchell@google.com> | 2021-06-02 21:54:40 +0000 |
commit | 99ae898d3cc484de91bd8df6c93514c25f0b0dce (patch) | |
tree | 7ff728cccba7456f3e0c2ed98f88f12c097e9923 | |
parent | a384fb763717ac0b841605b0b16b23784c09fc90 (diff) |
OMS: include idmap data in dump
Teach the overlay manager to ask the idmap service to pretty print the
contents of each idmap file as part of OMS dump. This creates a single
entry point for dumping both OMS and idmap data, and circumvents the
problem of accessing the idmap service if it has been killed due to
inactivity.
Example idmap section:
---- 8< ----
IDMAP OF com.android.theme.color.sand
Paths:
target path : /system/framework/framework-res.apk
overlay path : /product/overlay/AccentColorSand/AccentColorSandOverlay.apk
Debug info:
W failed to find resource 'string/accent_color_overlay'
Mapping:
0x0106006e -> 0x7f010000 (color/accent_device_default_dark -> color/accent_device_default_dark)
0x01060070 -> 0x7f010001 (color/accent_device_default_light -> color/accent_device_default_light)
---- >8 ----
Bug: 189963636
Test: adb exec-out dumpsys
Test: adb exec-out cmd overlay dump
Test: adb exec-out cmd overlay dump <overlay-identifier>
Change-Id: I9de6ba646ad4714c9d0f0d8081fbf632577107e7
7 files changed, 84 insertions, 3 deletions
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index 4f775aa52195..73a7240219af 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -33,6 +33,7 @@ #include "idmap2/BinaryStreamVisitor.h" #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" +#include "idmap2/PrettyPrintVisitor.h" #include "idmap2/Result.h" #include "idmap2/SysTrace.h" @@ -45,6 +46,7 @@ using android::idmap2::FabricatedOverlayContainer; using android::idmap2::Idmap; using android::idmap2::IdmapHeader; using android::idmap2::OverlayResourceContainer; +using android::idmap2::PrettyPrintVisitor; using android::idmap2::TargetResourceContainer; using android::idmap2::utils::kIdmapCacheDir; using android::idmap2::utils::kIdmapFilePermissionMask; @@ -352,4 +354,24 @@ binder::Status Idmap2Service::deleteFabricatedOverlay(const std::string& overlay return ok(); } +binder::Status Idmap2Service::dumpIdmap(const std::string& overlay_path, + std::string* _aidl_return) { + assert(_aidl_return); + + const auto idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_path); + std::ifstream fin(idmap_path); + const auto idmap = Idmap::FromBinaryStream(fin); + fin.close(); + if (!idmap) { + return error(idmap.GetErrorMessage()); + } + + std::stringstream stream; + PrettyPrintVisitor visitor(stream); + (*idmap)->accept(&visitor); + *_aidl_return = stream.str(); + + return ok(); +} + } // namespace android::os diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h index 4d16ff39884b..40843f75a3ab 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.h +++ b/cmds/idmap2/idmap2d/Idmap2Service.h @@ -60,6 +60,8 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 { binder::Status getFabricatedOverlayInfos( std::vector<os::FabricatedOverlayInfo>* _aidl_return) override; + binder::Status dumpIdmap(const std::string& overlay_path, std::string* _aidl_return) override; + private: // idmap2d is killed after a period of inactivity, so any information stored on this class should // be able to be recalculated if idmap2 dies and restarts. diff --git a/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl index 35bca98bcf69..48cee69ca779 100644 --- a/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl +++ b/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl @@ -16,8 +16,8 @@ package android.os; -import android.os.FabricatedOverlayInternal; import android.os.FabricatedOverlayInfo; +import android.os.FabricatedOverlayInternal; /** * @hide @@ -40,4 +40,5 @@ interface IIdmap2 { @nullable FabricatedOverlayInfo createFabricatedOverlay(in FabricatedOverlayInternal overlay); List<FabricatedOverlayInfo> getFabricatedOverlayInfos(); boolean deleteFabricatedOverlay(@utf8InCpp String path); + @utf8InCpp String dumpIdmap(@utf8InCpp String overlayApkPath); } diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java index 2ebc8edb6740..f2b6b1d53988 100644 --- a/services/core/java/com/android/server/om/IdmapDaemon.java +++ b/services/core/java/com/android/server/om/IdmapDaemon.java @@ -170,6 +170,16 @@ class IdmapDaemon { } } + String dumpIdmap(@NonNull String overlayPath) { + try (Connection c = connect()) { + String dump = mService.dumpIdmap(overlayPath); + return TextUtils.nullIfEmpty(dump); + } catch (Exception e) { + Slog.wtf(TAG, "failed to dump idmap", e); + return null; + } + } + private IBinder getIdmapService() throws TimeoutException, RemoteException { SystemService.start(IDMAP_DAEMON); diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index 64362c9b1d69..157a1fc4d12c 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -22,7 +22,6 @@ import static com.android.server.om.OverlayManagerService.TAG; import android.annotation.NonNull; import android.content.om.OverlayInfo; import android.content.om.OverlayableInfo; -import android.content.pm.PackageParser; import android.os.Build.VERSION_CODES; import android.os.FabricatedOverlayInfo; import android.os.FabricatedOverlayInternal; @@ -142,6 +141,14 @@ final class IdmapManager { } /** + * Gets the idmap data associated with an overlay, in dump format. + * Only indented for debugging. + */ + String dumpIdmap(@NonNull String overlayPath) { + return mIdmapDaemon.dumpIdmap(overlayPath); + } + + /** * Checks if overlayable and policies should be enforced on the specified overlay for backwards * compatibility with pre-Q overlays. */ diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 799ab4633b2a..e4ca5b6d04bb 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -22,6 +22,7 @@ import static android.content.om.OverlayInfo.STATE_MISSING_TARGET; import static android.content.om.OverlayInfo.STATE_NO_IDMAP; import static android.content.om.OverlayInfo.STATE_OVERLAY_IS_BEING_REPLACED; import static android.content.om.OverlayInfo.STATE_TARGET_IS_BEING_REPLACED; +import static android.os.UserHandle.USER_SYSTEM; import static com.android.server.om.OverlayManagerService.DEBUG; import static com.android.server.om.OverlayManagerService.TAG; @@ -38,6 +39,7 @@ import android.os.FabricatedOverlayInternal; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.Pair; import android.util.Slog; import com.android.internal.content.om.OverlayConfig; @@ -682,8 +684,38 @@ final class OverlayManagerServiceImpl { } void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) { + Pair<OverlayIdentifier, String> overlayIdmap = null; + if (dumpState.getPackageName() != null) { + OverlayIdentifier id = new OverlayIdentifier(dumpState.getPackageName(), + dumpState.getOverlayName()); + OverlayInfo oi = mSettings.getNullableOverlayInfo(id, USER_SYSTEM); + if (oi != null) { + overlayIdmap = new Pair<>(id, oi.baseCodePath); + } + } + + // settings mSettings.dump(pw, dumpState); - if (dumpState.getPackageName() == null) { + + // idmap data + if (dumpState.getField() == null) { + Set<Pair<OverlayIdentifier, String>> allIdmaps = (overlayIdmap != null) + ? Set.of(overlayIdmap) : mSettings.getAllIdentifiersAndBaseCodePaths(); + for (Pair<OverlayIdentifier, String> pair : allIdmaps) { + pw.println("IDMAP OF " + pair.first); + String dump = mIdmapManager.dumpIdmap(pair.second); + if (dump != null) { + pw.println(dump); + } else { + OverlayInfo oi = mSettings.getNullableOverlayInfo(pair.first, USER_SYSTEM); + pw.println((oi != null && !mIdmapManager.idmapExists(oi)) + ? "<missing idmap>" : "<internal error>"); + } + } + } + + // default overlays + if (overlayIdmap == null) { pw.println("Default overlays: " + TextUtils.join(";", mDefaultOverlays)); } } diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index e3e090663a89..55bca1733d37 100644 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java @@ -26,6 +26,7 @@ import android.content.om.OverlayInfo; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.Pair; import android.util.Slog; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; @@ -205,6 +206,12 @@ final class OverlayManagerSettings { return paths; } + Set<Pair<OverlayIdentifier, String>> getAllIdentifiersAndBaseCodePaths() { + final Set<Pair<OverlayIdentifier, String>> set = new ArraySet<>(); + mItems.forEach(item -> set.add(new Pair(item.mOverlay, item.mBaseCodePath))); + return set; + } + @NonNull List<OverlayInfo> removeIf(@NonNull final Predicate<OverlayInfo> predicate, final int userId) { return removeIf(info -> (predicate.test(info) && info.userId == userId)); |