diff options
| author | Darrell Shi <darrellshi@google.com> | 2022-02-04 00:51:59 +0000 |
|---|---|---|
| committer | Darrell Shi <darrellshi@google.com> | 2022-02-10 18:09:00 +0000 |
| commit | 91f91d7ae38cfa637d0a87a9fd546932522b1705 (patch) | |
| tree | 6caeb78bd4b664cfff393fa183cd5f1afd39c5e8 /core/java | |
| parent | b45c44cb17e9ac8536fa0702aa89348bbf616ff4 (diff) | |
(Resubmit) Move dream metadata parsing to framework.
Bug: 214117287
Test: atest com.android.server.dreams.DreamServiceTest
Test: manually on device by opening Screensaver settings because it
calls into the metadata parsing from DreamBackend
Change-Id: I252f634dd10297ba7dcd91fae6289a85a2904e3d
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/service/dreams/DreamService.java | 117 |
1 files changed, 115 insertions, 2 deletions
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index bb1f393b99bc..45ddbe4b0a18 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -31,6 +31,11 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.content.pm.ServiceInfo; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Handler; import android.os.IBinder; @@ -39,9 +44,11 @@ import android.os.Looper; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; +import android.util.AttributeSet; import android.util.Log; import android.util.MathUtils; import android.util.Slog; +import android.util.Xml; import android.view.ActionMode; import android.view.Display; import android.view.KeyEvent; @@ -59,7 +66,11 @@ import android.view.accessibility.AccessibilityEvent; import com.android.internal.util.DumpUtils; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import java.io.FileDescriptor; +import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.function.Consumer; @@ -159,8 +170,9 @@ import java.util.function.Consumer; * </pre> */ public class DreamService extends Service implements Window.Callback { - private final String mTag = - DreamService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]"; + private static final String TAG = DreamService.class.getSimpleName(); + private final String mTag = TAG + "[" + getClass().getSimpleName() + "]"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); /** * The name of the dream manager service. @@ -191,6 +203,11 @@ public class DreamService extends Service implements Window.Callback { public static final String DREAM_META_DATA = "android.service.dream"; /** + * Name of the root tag under which a Dream defines its metadata in an XML file. + */ + private static final String DREAM_META_DATA_ROOT_TAG = "dream"; + + /** * Extra containing a boolean for whether to show complications on the overlay. * @hide */ @@ -1081,6 +1098,84 @@ public class DreamService extends Service implements Window.Callback { // end public api /** + * Parses and returns metadata of the dream service indicated by the service info. Returns null + * if metadata cannot be found. + * + * Note that {@link ServiceInfo} must be fetched with {@link PackageManager#GET_META_DATA} flag. + * + * @hide + */ + @Nullable + public static DreamMetadata getDreamMetadata(Context context, ServiceInfo serviceInfo) { + final PackageManager pm = context.getPackageManager(); + + final TypedArray rawMetadata = readMetadata(pm, serviceInfo); + if (rawMetadata == null) return null; + + final DreamMetadata metadata = new DreamMetadata( + convertToComponentName(rawMetadata.getString( + com.android.internal.R.styleable.Dream_settingsActivity), serviceInfo), + rawMetadata.getDrawable( + com.android.internal.R.styleable.Dream_previewImage)); + rawMetadata.recycle(); + return metadata; + } + + /** + * Returns the raw XML metadata fetched from the {@link ServiceInfo}. + * + * Returns <code>null</code> if the {@link ServiceInfo} doesn't contain valid dream metadata. + */ + @Nullable + private static TypedArray readMetadata(PackageManager pm, ServiceInfo serviceInfo) { + if (serviceInfo == null || serviceInfo.metaData == null) { + return null; + } + + try (XmlResourceParser parser = + serviceInfo.loadXmlMetaData(pm, DreamService.DREAM_META_DATA)) { + if (parser == null) { + if (DEBUG) Log.w(TAG, "No " + DreamService.DREAM_META_DATA + " metadata"); + return null; + } + + final AttributeSet attrs = Xml.asAttributeSet(parser); + while (true) { + final int type = parser.next(); + if (type == XmlPullParser.END_DOCUMENT || type == XmlPullParser.START_TAG) { + break; + } + } + + if (!parser.getName().equals(DREAM_META_DATA_ROOT_TAG)) { + if (DEBUG) { + Log.w(TAG, "Metadata does not start with " + DREAM_META_DATA_ROOT_TAG + " tag"); + } + return null; + } + + return pm.getResourcesForApplication(serviceInfo.applicationInfo).obtainAttributes( + attrs, com.android.internal.R.styleable.Dream); + } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) { + if (DEBUG) Log.e(TAG, "Error parsing: " + serviceInfo.packageName, e); + return null; + } + } + + private static ComponentName convertToComponentName(String flattenedString, + ServiceInfo serviceInfo) { + if (flattenedString == null) { + return null; + } + + if (!flattenedString.contains("/")) { + return new ComponentName(serviceInfo.packageName, flattenedString); + } + + return ComponentName.unflattenFromString(flattenedString); + } + + /** * Called by DreamController.stopDream() when the Dream is about to be unbound and destroyed. * * Must run on mHandler. @@ -1302,4 +1397,22 @@ public class DreamService extends Service implements Window.Callback { onWindowCreated(a.getWindow()); } } + + /** + * Represents metadata defined in {@link android.R.styleable#Dream <dream>}. + * + * @hide + */ + public static final class DreamMetadata { + @Nullable + public final ComponentName settingsActivity; + + @Nullable + public final Drawable previewImage; + + DreamMetadata(ComponentName settingsActivity, Drawable previewImage) { + this.settingsActivity = settingsActivity; + this.previewImage = previewImage; + } + } } |
