summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorFelipe Leme <felipeal@google.com>2019-03-19 16:54:55 -0700
committerFelipe Leme <felipeal@google.com>2019-03-20 08:36:24 -0700
commita5d5e2db8f0d42de0c695df8d5583109f61865f9 (patch)
tree80f36731d9c241ce0652f30b5f9f7bb88dc4128b /core/java
parent5ca35d19a4810970eef095983e0b5c8c410cd6ad (diff)
Added manifest metadata to define the content capture settings activity.
Test: m update-api Test: mmm frameworks/base/:doc-comment-check-docs Test: adb shell dumpsys content_capture Test: CtsContentCaptureServiceTestCases Bug: 119264902 Change-Id: I656c50d9a45f68312898c8857572d5fe3f55c193
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java15
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureServiceInfo.java171
2 files changed, 186 insertions, 0 deletions
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 6f4114d1d81a..df113979bacf 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -78,6 +78,21 @@ public abstract class ContentCaptureService extends Service {
public static final String SERVICE_INTERFACE =
"android.service.contentcapture.ContentCaptureService";
+ /**
+ * Name under which a ContentCaptureService component publishes information about itself.
+ *
+ * <p>This meta-data should reference an XML resource containing a
+ * <code>&lt;{@link
+ * android.R.styleable#ContentCaptureService content-capture-service}&gt;</code> tag.
+ *
+ * <p>This is a a sample XML file configuring a ContentCaptureService:
+ * <pre> &lt;content-capture-service
+ * android:settingsActivity="foo.bar.SettingsActivity"
+ * . . .
+ * /&gt;</pre>
+ */
+ public static final String SERVICE_META_DATA = "android.content_capture";
+
private Handler mHandler;
private IContentCaptureServiceCallback mCallback;
diff --git a/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java b/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java
new file mode 100644
index 000000000000..6ecd82f50fdb
--- /dev/null
+++ b/core/java/android/service/contentcapture/ContentCaptureServiceInfo.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package android.service.contentcapture;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * {@link ServiceInfo} and meta-data about an {@link ContentCaptureService}.
+ *
+ * @hide
+ */
+public final class ContentCaptureServiceInfo {
+
+ private static final String TAG = ContentCaptureServiceInfo.class.getSimpleName();
+ private static final String XML_TAG_SERVICE = "content-capture-service";
+
+ private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, boolean isTemp,
+ @UserIdInt int userId) throws PackageManager.NameNotFoundException {
+ int flags = PackageManager.GET_META_DATA;
+ if (!isTemp) {
+ flags |= PackageManager.MATCH_SYSTEM_ONLY;
+ }
+
+ ServiceInfo si = null;
+ try {
+ si = AppGlobals.getPackageManager().getServiceInfo(comp, flags, userId);
+ } catch (RemoteException e) {
+ }
+ if (si == null) {
+ throw new NameNotFoundException("Could not get serviceInfo for "
+ + (isTemp ? " (temp)" : "(default system)")
+ + " " + comp.flattenToShortString());
+ }
+ return si;
+ }
+
+ @NonNull
+ private final ServiceInfo mServiceInfo;
+
+ @Nullable
+ private final String mSettingsActivity;
+
+ public ContentCaptureServiceInfo(@NonNull Context context, @NonNull ComponentName comp,
+ boolean isTemporaryService, @UserIdInt int userId)
+ throws PackageManager.NameNotFoundException {
+ this(context, getServiceInfoOrThrow(comp, isTemporaryService, userId));
+ }
+
+ private ContentCaptureServiceInfo(@NonNull Context context, @NonNull ServiceInfo si) {
+ // Check for permissions.
+ if (!Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE.equals(si.permission)) {
+ Slog.w(TAG, "ContentCaptureService from '" + si.packageName
+ + "' does not require permission "
+ + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
+ throw new SecurityException("Service does not require permission "
+ + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
+ }
+
+ mServiceInfo = si;
+
+ // Get the metadata, if declared.
+ final XmlResourceParser parser = si.loadXmlMetaData(context.getPackageManager(),
+ ContentCaptureService.SERVICE_META_DATA);
+ if (parser == null) {
+ mSettingsActivity = null;
+ return;
+ }
+
+ String settingsActivity = null;
+
+ try {
+ final Resources resources = context.getPackageManager().getResourcesForApplication(
+ si.applicationInfo);
+
+ int type = 0;
+ while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
+ type = parser.next();
+ }
+
+ if (XML_TAG_SERVICE.equals(parser.getName())) {
+ final AttributeSet allAttributes = Xml.asAttributeSet(parser);
+ TypedArray afsAttributes = null;
+ try {
+ afsAttributes = resources.obtainAttributes(allAttributes,
+ com.android.internal.R.styleable.ContentCaptureService);
+ settingsActivity = afsAttributes.getString(
+ R.styleable.ContentCaptureService_settingsActivity);
+ } finally {
+ if (afsAttributes != null) {
+ afsAttributes.recycle();
+ }
+ }
+ } else {
+ Log.e(TAG, "Meta-data does not start with content-capture-service tag");
+ }
+ } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) {
+ Log.e(TAG, "Error parsing auto fill service meta-data", e);
+ }
+
+ mSettingsActivity = settingsActivity;
+ }
+
+ public ServiceInfo getServiceInfo() {
+ return mServiceInfo;
+ }
+
+ @Nullable
+ public String getSettingsActivity() {
+ return mSettingsActivity;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(getClass().getSimpleName());
+ builder.append("[").append(mServiceInfo);
+ builder.append(", settings:").append(mSettingsActivity);
+ return builder.toString();
+ }
+
+ /**
+ * Dumps it!
+ */
+ public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
+ pw.print(prefix);
+ pw.print("Component: ");
+ pw.println(getServiceInfo().getComponentName());
+ pw.print(prefix);
+ pw.print("Settings: ");
+ pw.println(mSettingsActivity);
+ }
+}