diff options
| author | 2017-02-10 14:38:39 -0800 | |
|---|---|---|
| committer | 2017-02-23 09:34:32 -0800 | |
| commit | 426cbefdf3c78bd0aa80b180ffc1fb8b5a226bc3 (patch) | |
| tree | 10fbea15074aeaccd9af0ab789ca98b3ca1f8ce5 | |
| parent | 189796dace361bb426b8dffd9d8d167b4a4ee59b (diff) | |
Protobufferize PackageManager dumpsys
Bug: 34230809
Test: cts-tradefed run cts-dev -m CtsIncidentHostTestCase -t com.android.server.cts.PackageIncidentTest
Change-Id: I6dc455db47a8a636267cf7abe993e135e9044b33
5 files changed, 304 insertions, 3 deletions
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto new file mode 100644 index 000000000000..326b0eb6c508 --- /dev/null +++ b/core/proto/android/service/package.proto @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +package android.service.pm; + +option java_multiple_files = true; +option java_outer_classname = "PackageServiceProto"; + +message PackageServiceDumpProto { + message PackageShortProto { + // Name of package. e.g. "com.android.providers.telephony". + string name = 1; + // UID for this package as assigned by Android OS. + int32 uid = 2; + } + message SharedLibraryProto { + string name = 1; + // True if library path is not null (jar), false otherwise (apk) + bool is_jar = 2; + // Should be filled if is_jar is true + string path = 3; + // Should be filled if is_jar is false + string apk = 4; + } + message FeatureProto { + string name = 1; + int32 version = 2; + } + message SharedUserProto { + int32 user_id = 1; + string name = 2; + } + + // Installed packages. + PackageShortProto required_verifier_package = 1; + PackageShortProto verifier_package = 2; + repeated SharedLibraryProto shared_libraries = 3; + repeated FeatureProto features = 4; + repeated PackageProto packages = 5; + repeated SharedUserProto shared_users = 6; + // Messages from the settings problem file + repeated string messages = 7; +} + +message PackageProto { + message SplitProto { + string name = 1; + int32 revision_code = 2; + } + message UserInfoProto { + enum InstallType { + NOT_INSTALLED_FOR_USER = 0; + FULL_APP_INSTALL = 1; + INSTANT_APP_INSTALL = 2; + } + // Enum values gotten from PackageManger.java + enum EnabledState { + // This component or application is in its default enabled state + // (as specified in its manifest). + COMPONENT_ENABLED_STATE_DEFAULT = 0; + // This component or application has been explictily enabled, regardless + // of what it has specified in its manifest. + COMPONENT_ENABLED_STATE_ENABLED = 1; + // This component or application has been explicitly disabled, regardless of + // what it has specified in its manifest. + COMPONENT_ENABLED_STATE_DISABLED = 2; + // The user has explicitly disabled the application, regardless of what it has + // specified in its manifest. + COMPONENT_ENABLED_STATE_DISABLED_USER = 3; + // This application should be considered, until the point where the user actually + // wants to use it. + COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; + } + + int32 id = 1; + InstallType install_type = 2; + // Is the app restricted by owner / admin + bool is_hidden = 3; + bool is_suspended = 4; + bool is_stopped = 5; + bool is_launched = 6; + EnabledState enabled_state = 7; + string last_disabled_app_caller = 8; + } + + // Name of package. e.g. "com.android.providers.telephony". + string name = 1; + // UID for this package as assigned by Android OS. + int32 uid = 2; + // Package's reported version. + int32 version_code = 3; + // Package's reported version string (what's displayed to the user). + string version_string = 4; + // UTC timestamp of install + int64 install_time_ms = 5; + // Millisecond UTC timestamp of latest update adjusted to Google's server clock. + int64 update_time_ms = 6; + // From "dumpsys package" - name of package which installed this one. + // Typically "" if system app or "com.android.vending" if Play Store. + string installer_name = 7; + // Split APKs. + repeated SplitProto splits = 8; + // Per-user package info. + repeated UserInfoProto users = 9; +} diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 975ae0654626..430c805e54ac 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -128,7 +128,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.AppsQueryHelper; import android.content.pm.ChangedPackages; import android.content.pm.ComponentInfo; -import android.content.pm.InstantAppInfo; import android.content.pm.EphemeralRequest; import android.content.pm.EphemeralResolveInfo; import android.content.pm.EphemeralResponse; @@ -143,6 +142,7 @@ import android.content.pm.IPackageInstaller; import android.content.pm.IPackageManager; import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageStatsObserver; +import android.content.pm.InstantAppInfo; import android.content.pm.InstrumentationInfo; import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.KeySet; @@ -204,15 +204,16 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.storage.IStorageManager; -import android.os.storage.StorageManagerInternal; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; +import android.os.storage.StorageManagerInternal; import android.os.storage.VolumeInfo; import android.os.storage.VolumeRecord; import android.provider.Settings.Global; import android.provider.Settings.Secure; import android.security.KeyStore; import android.security.SystemKeyStore; +import android.service.pm.PackageServiceDumpProto; import android.system.ErrnoException; import android.system.Os; import android.text.TextUtils; @@ -235,6 +236,7 @@ import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.Xml; import android.util.jar.StrictJarFile; +import android.util.proto.ProtoOutputStream; import android.view.Display; import com.android.internal.R; @@ -316,8 +318,8 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; -import java.util.HashSet; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -20284,6 +20286,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); checkin = true; } else if ("-f".equals(opt)) { dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS); + } else if ("--proto".equals(opt)) { + dumpProto(fd); + return; } else { pw.println("Unknown argument: " + opt + "; use -h for help"); } @@ -20814,6 +20819,98 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } } + private void dumpProto(FileDescriptor fd) { + final ProtoOutputStream proto = new ProtoOutputStream(fd); + + synchronized (mPackages) { + final long requiredVerifierPackageToken = + proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE); + proto.write(PackageServiceDumpProto.PackageShortProto.NAME, mRequiredVerifierPackage); + proto.write( + PackageServiceDumpProto.PackageShortProto.UID, + getPackageUid( + mRequiredVerifierPackage, + MATCH_DEBUG_TRIAGED_MISSING, + UserHandle.USER_SYSTEM)); + proto.end(requiredVerifierPackageToken); + + if (mIntentFilterVerifierComponent != null) { + String verifierPackageName = mIntentFilterVerifierComponent.getPackageName(); + final long verifierPackageToken = + proto.start(PackageServiceDumpProto.VERIFIER_PACKAGE); + proto.write(PackageServiceDumpProto.PackageShortProto.NAME, verifierPackageName); + proto.write( + PackageServiceDumpProto.PackageShortProto.UID, + getPackageUid( + verifierPackageName, + MATCH_DEBUG_TRIAGED_MISSING, + UserHandle.USER_SYSTEM)); + proto.end(verifierPackageToken); + } + + dumpSharedLibrariesProto(proto); + dumpFeaturesProto(proto); + mSettings.dumpPackagesProto(proto); + mSettings.dumpSharedUsersProto(proto); + dumpMessagesProto(proto); + } + proto.flush(); + } + + private void dumpMessagesProto(ProtoOutputStream proto) { + BufferedReader in = null; + String line = null; + try { + in = new BufferedReader(new FileReader(getSettingsProblemFile())); + while ((line = in.readLine()) != null) { + if (line.contains("ignored: updated version")) continue; + proto.write(PackageServiceDumpProto.MESSAGES, line); + } + } catch (IOException ignored) { + } finally { + IoUtils.closeQuietly(in); + } + } + + private void dumpFeaturesProto(ProtoOutputStream proto) { + synchronized (mAvailableFeatures) { + final int count = mAvailableFeatures.size(); + for (int i = 0; i < count; i++) { + final FeatureInfo feat = mAvailableFeatures.valueAt(i); + final long featureToken = proto.start(PackageServiceDumpProto.FEATURES); + proto.write(PackageServiceDumpProto.FeatureProto.NAME, feat.name); + proto.write(PackageServiceDumpProto.FeatureProto.VERSION, feat.version); + proto.end(featureToken); + } + } + } + + private void dumpSharedLibrariesProto(ProtoOutputStream proto) { + final int count = mSharedLibraries.size(); + for (int i = 0; i < count; i++) { + final String libName = mSharedLibraries.keyAt(i); + SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(libName); + if (versionedLib == null) { + continue; + } + final int versionCount = versionedLib.size(); + for (int j = 0; j < versionCount; j++) { + final SharedLibraryEntry libEntry = versionedLib.valueAt(j); + final long sharedLibraryToken = + proto.start(PackageServiceDumpProto.SHARED_LIBRARIES); + proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libEntry.info.getName()); + final boolean isJar = (libEntry.path != null); + proto.write(PackageServiceDumpProto.SharedLibraryProto.IS_JAR, isJar); + if (isJar) { + proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH, libEntry.path); + } else { + proto.write(PackageServiceDumpProto.SharedLibraryProto.APK, libEntry.apk); + } + proto.end(sharedLibraryToken); + } + } + } + private void dumpDexoptStateLPr(PrintWriter pw, String packageName) { final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120); ipw.println(); diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 5f348abd3b8d..b4bba88eaf84 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -19,6 +19,9 @@ package com.android.server.pm; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; +import android.content.pm.UserInfo; +import android.service.pm.PackageProto; +import android.util.proto.ProtoOutputStream; import java.io.File; import java.util.List; @@ -128,4 +131,32 @@ final class PackageSetting extends PackageSettingBase { } return true; } + + public void writeToProto(ProtoOutputStream proto, long fieldId, List<UserInfo> users) { + final long packageToken = proto.start(fieldId); + proto.write(PackageProto.NAME, (realName != null ? realName : name)); + proto.write(PackageProto.UID, appId); + proto.write(PackageProto.VERSION_CODE, versionCode); + proto.write(PackageProto.VERSION_STRING, pkg.mVersionName); + proto.write(PackageProto.INSTALL_TIME_MS, firstInstallTime); + proto.write(PackageProto.UPDATE_TIME_MS, lastUpdateTime); + proto.write(PackageProto.INSTALLER_NAME, installerPackageName); + + if (pkg != null) { + long splitToken = proto.start(PackageProto.SPLITS); + proto.write(PackageProto.SplitProto.NAME, "base"); + proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.baseRevisionCode); + proto.end(splitToken); + if (pkg.splitNames != null) { + for (int i = 0; i < pkg.splitNames.length; i++) { + splitToken = proto.start(PackageProto.SPLITS); + proto.write(PackageProto.SplitProto.NAME, pkg.splitNames[i]); + proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.splitRevisionCodes[i]); + proto.end(splitToken); + } + } + } + writeUsersInfoToProto(proto, PackageProto.USERS); + proto.end(packageToken); + } } diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 601377d6f8d2..b9c43da77916 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -25,8 +25,10 @@ import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageUserState; import android.os.storage.VolumeInfo; +import android.service.pm.PackageProto; import android.util.ArraySet; import android.util.SparseArray; +import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -564,4 +566,32 @@ abstract class PackageSettingBase extends SettingBase { modifyUserState(userId).domainVerificationStatus = PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; } + + protected void writeUsersInfoToProto(ProtoOutputStream proto, long fieldId) { + int count = userState.size(); + for (int i = 0; i < count; i++) { + final long userToken = proto.start(fieldId); + final int userId = userState.keyAt(i); + final PackageUserState state = userState.valueAt(i); + proto.write(PackageProto.UserInfoProto.ID, userId); + final int installType; + if (state.instantApp) { + installType = PackageProto.UserInfoProto.INSTANT_APP_INSTALL; + } else if (state.installed) { + installType = PackageProto.UserInfoProto.FULL_APP_INSTALL; + } else { + installType = PackageProto.UserInfoProto.NOT_INSTALLED_FOR_USER; + } + proto.write(PackageProto.UserInfoProto.INSTALL_TYPE, installType); + proto.write(PackageProto.UserInfoProto.IS_HIDDEN, state.hidden); + proto.write(PackageProto.UserInfoProto.IS_SUSPENDED, state.suspended); + proto.write(PackageProto.UserInfoProto.IS_STOPPED, state.stopped); + proto.write(PackageProto.UserInfoProto.IS_LAUNCHED, !state.notLaunched); + proto.write(PackageProto.UserInfoProto.ENABLED_STATE, state.enabled); + proto.write( + PackageProto.UserInfoProto.LAST_DISABLED_APP_CALLER, + state.lastDisableAppCaller); + proto.end(userToken); + } + } } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index a8a5ff056521..0533c17b65cf 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -65,6 +65,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; +import android.service.pm.PackageServiceDumpProto; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -77,6 +78,7 @@ import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.Xml; +import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.BackgroundThread; @@ -4876,6 +4878,16 @@ final class Settings { } } + void dumpPackagesProto(ProtoOutputStream proto) { + List<UserInfo> users = getAllUsers(UserManagerService.getInstance()); + + final int count = mPackages.size(); + for (int i = 0; i < count; i++) { + final PackageSetting ps = mPackages.valueAt(i); + ps.writeToProto(proto, PackageServiceDumpProto.PACKAGES, users); + } + } + void dumpPermissionsLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames, DumpState dumpState) { boolean printedSomething = false; @@ -4966,6 +4978,17 @@ final class Settings { } } + void dumpSharedUsersProto(ProtoOutputStream proto) { + final int count = mSharedUsers.size(); + for (int i = 0; i < count; i++) { + final SharedUserSetting su = mSharedUsers.valueAt(i); + final long sharedUserToken = proto.start(PackageServiceDumpProto.SHARED_USERS); + proto.write(PackageServiceDumpProto.SharedUserProto.USER_ID, su.userId); + proto.write(PackageServiceDumpProto.SharedUserProto.NAME, su.name); + proto.end(sharedUserToken); + } + } + void dumpReadMessagesLPr(PrintWriter pw, DumpState dumpState) { pw.println("Settings parse messages:"); pw.print(mReadMessages.toString()); |