AutofillServiceInfo.java revision f78e952d8df7074aa7380c5998826a4dffe335e7
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.service.autofill; 17 18import android.Manifest; 19import android.annotation.NonNull; 20import android.annotation.Nullable; 21import android.app.AppGlobals; 22import android.content.ComponentName; 23import android.content.pm.PackageManager; 24import android.content.pm.ServiceInfo; 25import android.content.res.Resources; 26import android.content.res.TypedArray; 27import android.content.res.XmlResourceParser; 28import android.os.RemoteException; 29import android.util.AttributeSet; 30import android.util.Log; 31import android.util.Xml; 32import org.xmlpull.v1.XmlPullParser; 33import org.xmlpull.v1.XmlPullParserException; 34 35import com.android.internal.R; 36 37import java.io.IOException; 38 39/** 40 * {@link ServiceInfo} and meta-data about an {@link AutofillService}. 41 * 42 * @hide 43 */ 44public final class AutofillServiceInfo { 45 private static final String TAG = "AutofillServiceInfo"; 46 47 private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle) 48 throws PackageManager.NameNotFoundException { 49 try { 50 ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo( 51 comp, 52 PackageManager.GET_META_DATA, 53 userHandle); 54 if (si != null) { 55 return si; 56 } 57 } catch (RemoteException e) { 58 } 59 throw new PackageManager.NameNotFoundException(comp.toString()); 60 } 61 62 @NonNull 63 private final ServiceInfo mServiceInfo; 64 65 @Nullable 66 private final String mSettingsActivity; 67 68 public AutofillServiceInfo(PackageManager pm, ComponentName comp, int userHandle) 69 throws PackageManager.NameNotFoundException { 70 this(pm, getServiceInfoOrThrow(comp, userHandle)); 71 } 72 73 public AutofillServiceInfo(PackageManager pm, ServiceInfo si) { 74 mServiceInfo = si; 75 final TypedArray metaDataArray = getMetaDataArray(pm, si); 76 if (metaDataArray != null) { 77 mSettingsActivity = metaDataArray 78 .getString(R.styleable.AutofillService_settingsActivity); 79 metaDataArray.recycle(); 80 } else { 81 mSettingsActivity = null; 82 } 83 } 84 85 /** 86 * Gets the meta-data as a TypedArray, or null if not provided, or throws if invalid. 87 */ 88 @Nullable 89 private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) { 90 // Check for permissions. 91 if (!Manifest.permission.BIND_AUTOFILL.equals(si.permission)) { 92 Log.e(TAG, "Service does not require permission " + Manifest.permission.BIND_AUTOFILL); 93 return null; 94 } 95 96 // Get the AutoFill metadata, if declared. 97 XmlResourceParser parser = si.loadXmlMetaData(pm, AutofillService.SERVICE_META_DATA); 98 if (parser == null) { 99 return null; 100 } 101 102 // Parse service info and get the <autofill-service> tag as an AttributeSet. 103 AttributeSet attrs; 104 try { 105 // Move the XML parser to the first tag. 106 try { 107 int type; 108 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 109 && type != XmlPullParser.START_TAG) { 110 } 111 } catch (XmlPullParserException | IOException e) { 112 Log.e(TAG, "Error parsing auto fill service meta-data", e); 113 return null; 114 } 115 116 if (!"autofill-service".equals(parser.getName())) { 117 Log.e(TAG, "Meta-data does not start with autofill-service tag"); 118 return null; 119 } 120 attrs = Xml.asAttributeSet(parser); 121 122 // Get resources required to read the AttributeSet. 123 Resources res; 124 try { 125 res = pm.getResourcesForApplication(si.applicationInfo); 126 } catch (PackageManager.NameNotFoundException e) { 127 Log.e(TAG, "Error getting application resources", e); 128 return null; 129 } 130 131 return res.obtainAttributes(attrs, R.styleable.AutofillService); 132 } finally { 133 parser.close(); 134 } 135 } 136 137 public ServiceInfo getServiceInfo() { 138 return mServiceInfo; 139 } 140 141 @Nullable 142 public String getSettingsActivity() { 143 return mSettingsActivity; 144 } 145} 146