diff options
| author | Felipe Leme <felipeal@google.com> | 2019-03-19 16:54:55 -0700 |
|---|---|---|
| committer | Felipe Leme <felipeal@google.com> | 2019-03-20 08:36:24 -0700 |
| commit | a5d5e2db8f0d42de0c695df8d5583109f61865f9 (patch) | |
| tree | 80f36731d9c241ce0652f30b5f9f7bb88dc4128b /core/java | |
| parent | 5ca35d19a4810970eef095983e0b5c8c410cd6ad (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.java | 15 | ||||
| -rw-r--r-- | core/java/android/service/contentcapture/ContentCaptureServiceInfo.java | 171 |
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><{@link + * android.R.styleable#ContentCaptureService content-capture-service}></code> tag. + * + * <p>This is a a sample XML file configuring a ContentCaptureService: + * <pre> <content-capture-service + * android:settingsActivity="foo.bar.SettingsActivity" + * . . . + * /></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); + } +} |
