AutofillServiceInfo.java revision 640f30a7763b0a4b80c767acb84c740aac04768b
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// TODO(b/33197203 , b/33802548): add CTS tests 40/** 41 * {@link ServiceInfo} and meta-data about an {@link AutofillService}. 42 * 43 * @hide 44 */ 45public final class AutofillServiceInfo { 46 private static final String TAG = "AutofillServiceInfo"; 47 48 private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle) 49 throws PackageManager.NameNotFoundException { 50 try { 51 ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo( 52 comp, 53 PackageManager.GET_META_DATA, 54 userHandle); 55 if (si != null) { 56 return si; 57 } 58 } catch (RemoteException e) { 59 } 60 throw new PackageManager.NameNotFoundException(comp.toString()); 61 } 62 63 @NonNull 64 private final ServiceInfo mServiceInfo; 65 66 @Nullable 67 private final String mSettingsActivity; 68 69 public AutofillServiceInfo(PackageManager pm, ComponentName comp, int userHandle) 70 throws PackageManager.NameNotFoundException { 71 this(pm, getServiceInfoOrThrow(comp, userHandle)); 72 } 73 74 public AutofillServiceInfo(PackageManager pm, ServiceInfo si) { 75 mServiceInfo = si; 76 final TypedArray metaDataArray = getMetaDataArray(pm, si); 77 if (metaDataArray != null) { 78 // TODO(b/35956626): inline newSettingsActivity once clients migrate 79 final String newSettingsActivity = 80 metaDataArray.getString(R.styleable.AutofillService_settingsActivity); 81 System.out.println(">>> NEW CRAP MAN: " + newSettingsActivity); // TODO(felipeal): tmp 82 if (newSettingsActivity != null) { 83 mSettingsActivity = newSettingsActivity; 84 } else { 85 mSettingsActivity = 86 metaDataArray.getString(R.styleable.AutoFillService_settingsActivity); 87 } 88 System.out.println(">>> FINAL CRAP MAN: " + mSettingsActivity); // TODO(felipeal): tmp 89 metaDataArray.recycle(); 90 } else { 91 mSettingsActivity = null; 92 } 93 } 94 95 /** 96 * Gets the meta-data as a TypedArray, or null if not provided, or throws if invalid. 97 */ 98 @Nullable 99 private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) { 100 // Check for permissions. 101 // TODO(b/35956626): remove check for BIND_AUTO_FILL once clients migrate 102 if (!Manifest.permission.BIND_AUTOFILL.equals(si.permission) 103 && !Manifest.permission.BIND_AUTO_FILL.equals(si.permission)) { 104 Log.e(TAG, "Service does not require permission " + Manifest.permission.BIND_AUTOFILL); 105 return null; 106 } 107 108 // TODO(b/35956626): remove once clients migrate 109 final boolean oldStyle = !Manifest.permission.BIND_AUTOFILL.equals(si.permission); 110 111 // Get the AutoFill metadata, if declared. 112 XmlResourceParser parser = si.loadXmlMetaData(pm, AutofillService.SERVICE_META_DATA); 113 if (parser == null) { 114 return null; 115 } 116 117 // Parse service info and get the <autofill-service> tag as an AttributeSet. 118 AttributeSet attrs; 119 try { 120 // Move the XML parser to the first tag. 121 try { 122 int type; 123 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 124 && type != XmlPullParser.START_TAG) { 125 } 126 } catch (XmlPullParserException | IOException e) { 127 Log.e(TAG, "Error parsing auto fill service meta-data", e); 128 return null; 129 } 130 131 if (!"autofill-service".equals(parser.getName())) { 132 Log.e(TAG, "Meta-data does not start with autofill-service tag"); 133 return null; 134 } 135 attrs = Xml.asAttributeSet(parser); 136 137 // Get resources required to read the AttributeSet. 138 Resources res; 139 try { 140 res = pm.getResourcesForApplication(si.applicationInfo); 141 } catch (PackageManager.NameNotFoundException e) { 142 Log.e(TAG, "Error getting application resources", e); 143 return null; 144 } 145 146 return oldStyle ? res.obtainAttributes(attrs, R.styleable.AutoFillService) 147 : res.obtainAttributes(attrs, R.styleable.AutofillService); 148 } finally { 149 parser.close(); 150 } 151 } 152 153 public ServiceInfo getServiceInfo() { 154 return mServiceInfo; 155 } 156 157 @Nullable 158 public String getSettingsActivity() { 159 return mSettingsActivity; 160 } 161} 162