diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index ac9ebe06ae0eb..9beae08cb331e 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -20,6 +20,7 @@ option java_multiple_files = true; option java_outer_classname = "IncidentProtoMetadata"; import "frameworks/base/libs/incident/proto/android/privacy.proto"; +import "frameworks/base/core/proto/android/service/appwidget.proto"; import "frameworks/base/core/proto/android/service/fingerprint.proto"; import "frameworks/base/core/proto/android/service/netstats.proto"; import "frameworks/base/core/proto/android/providers/settings.proto"; @@ -53,4 +54,5 @@ message IncidentProto { android.service.fingerprint.FingerprintServiceDumpProto fingerprint = 3000; android.service.NetworkStatsServiceDumpProto netstats = 3001; android.providers.settings.SettingsServiceDumpProto settings = 3002; + android.service.appwidget.AppWidgetServiceDumpProto appwidget = 3003; } diff --git a/core/proto/android/service/appwidget.proto b/core/proto/android/service/appwidget.proto new file mode 100644 index 0000000000000..1f04f71bb1219 --- /dev/null +++ b/core/proto/android/service/appwidget.proto @@ -0,0 +1,40 @@ +/* + * 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.appwidget; + +option java_multiple_files = true; +option java_outer_classname = "AppWidgetServiceProto"; + +// represents the object holding the dump info of the app widget service +message AppWidgetServiceDumpProto { + repeated WidgetProto widgets = 1; // the array of bound widgets +} + +// represents a bound widget +message WidgetProto { + bool isCrossProfile = 1; // true if host and provider belong to diff users + bool isHostStopped = 2; // true if host has not called startListening yet + string hostPackage = 3; + string providerPackage = 4; + string providerClass = 5; + int32 minWidth = 6; + int32 minHeight = 7; + int32 maxWidth = 8; + int32 maxHeight = 9; +} diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index ce50b301ddbef..4d2b10610fa8b 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -71,6 +71,8 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; +import android.service.appwidget.AppWidgetServiceDumpProto; +import android.service.appwidget.WidgetProto; import android.text.TextUtils; import android.util.ArraySet; import android.util.AtomicFile; @@ -83,6 +85,7 @@ import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.TypedValue; import android.util.Xml; +import android.util.proto.ProtoOutputStream; import android.view.Display; import android.view.View; import android.view.WindowManager; @@ -717,34 +720,78 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku + ", uid=" + Binder.getCallingUid()); synchronized (mLock) { - int N = mProviders.size(); - pw.println("Providers:"); - for (int i = 0; i < N; i++) { - dumpProvider(mProviders.get(i), i, pw); + if (args.length > 0 && "--proto".equals(args[0])) { + dumpProto(fd); + } else { + dumpInternal(pw); } + } + } - N = mWidgets.size(); - pw.println(" "); - pw.println("Widgets:"); - for (int i = 0; i < N; i++) { - dumpWidget(mWidgets.get(i), i, pw); - } + private void dumpProto(FileDescriptor fd) { + Slog.i(TAG, "dump proto for " + mWidgets.size() + " widgets"); - N = mHosts.size(); - pw.println(" "); - pw.println("Hosts:"); - for (int i = 0; i < N; i++) { - dumpHost(mHosts.get(i), i, pw); - } + ProtoOutputStream proto = new ProtoOutputStream(fd); + int N = mWidgets.size(); + for (int i=0; i < N; i++) { + dumpProtoWidget(proto, mWidgets.get(i)); + } + proto.flush(); + } + private void dumpProtoWidget(ProtoOutputStream proto, Widget widget) { + if (widget.host == null || widget.provider == null) { + Slog.d(TAG, "skip dumping widget because host or provider is null: widget.host=" + + widget.host + " widget.provider=" + widget.provider); + return; + } + long token = proto.start(AppWidgetServiceDumpProto.WIDGETS); + proto.write(WidgetProto.IS_CROSS_PROFILE, + widget.host.getUserId() != widget.provider.getUserId()); + proto.write(WidgetProto.IS_HOST_STOPPED, widget.host.callbacks == null); + proto.write(WidgetProto.HOST_PACKAGE, widget.host.id.packageName); + proto.write(WidgetProto.PROVIDER_PACKAGE, widget.provider.id.componentName.getPackageName()); + proto.write(WidgetProto.PROVIDER_CLASS, widget.provider.id.componentName.getClassName()); + if (widget.options != null) { + proto.write(WidgetProto.MIN_WIDTH, + widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 0)); + proto.write(WidgetProto.MIN_HEIGHT, + widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 0)); + proto.write(WidgetProto.MAX_WIDTH, + widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 0)); + proto.write(WidgetProto.MAX_HEIGHT, + widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 0)); + } + proto.end(token); + } - N = mPackagesWithBindWidgetPermission.size(); - pw.println(" "); - pw.println("Grants:"); - for (int i = 0; i < N; i++) { - Pair grant = mPackagesWithBindWidgetPermission.valueAt(i); - dumpGrant(grant, i, pw); - } + private void dumpInternal(PrintWriter pw) { + int N = mProviders.size(); + pw.println("Providers:"); + for (int i = 0; i < N; i++) { + dumpProvider(mProviders.get(i), i, pw); + } + + N = mWidgets.size(); + pw.println(" "); + pw.println("Widgets:"); + for (int i = 0; i < N; i++) { + dumpWidget(mWidgets.get(i), i, pw); + } + + N = mHosts.size(); + pw.println(" "); + pw.println("Hosts:"); + for (int i = 0; i < N; i++) { + dumpHost(mHosts.get(i), i, pw); + } + + N = mPackagesWithBindWidgetPermission.size(); + pw.println(" "); + pw.println("Grants:"); + for (int i = 0; i < N; i++) { + Pair grant = mPackagesWithBindWidgetPermission.valueAt(i); + dumpGrant(grant, i, pw); } }