15381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme/* 25381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * Copyright (C) 2016 The Android Open Source Project 35381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * 45381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License"); 55381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * you may not use this file except in compliance with the License. 65381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * You may obtain a copy of the License at 75381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * 85381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * http://www.apache.org/licenses/LICENSE-2.0 95381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * 105381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * Unless required by applicable law or agreed to in writing, software 115381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS, 125381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * See the License for the specific language governing permissions and 145381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme * limitations under the License. 155381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme */ 165381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Lemepackage android.service.autofill; 175381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme 185381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Lemeimport android.Manifest; 190f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganovimport android.annotation.NonNull; 204b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport android.annotation.Nullable; 215381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Lemeimport android.app.AppGlobals; 225381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Lemeimport android.content.ComponentName; 235381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Lemeimport android.content.pm.PackageManager; 245381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Lemeimport android.content.pm.ServiceInfo; 254b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport android.content.res.Resources; 264b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport android.content.res.TypedArray; 274b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport android.content.res.XmlResourceParser; 285381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Lemeimport android.os.RemoteException; 294b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport android.util.AttributeSet; 304b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport android.util.Log; 314b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport android.util.Xml; 324b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport org.xmlpull.v1.XmlPullParser; 334b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport org.xmlpull.v1.XmlPullParserException; 344b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long 35c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Longimport com.android.internal.R; 36c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long 374b93f46130ab9a972773ebf2be9839109d5c6a08Jason Longimport java.io.IOException; 385381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme 39c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long/** 40640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme * {@link ServiceInfo} and meta-data about an {@link AutofillService}. 41c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long * 42c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long * @hide 43c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long */ 44640f30a7763b0a4b80c767acb84c740aac04768bFelipe Lemepublic final class AutofillServiceInfo { 45640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme private static final String TAG = "AutofillServiceInfo"; 465381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme 475381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle) 485381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme throws PackageManager.NameNotFoundException { 495381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme try { 504b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo( 514b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long comp, 524b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long PackageManager.GET_META_DATA, 534b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long userHandle); 545381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme if (si != null) { 555381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme return si; 565381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme } 575381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme } catch (RemoteException e) { 585381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme } 595381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme throw new PackageManager.NameNotFoundException(comp.toString()); 605381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme } 615381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme 620f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov @NonNull 63c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long private final ServiceInfo mServiceInfo; 640f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov 654b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long @Nullable 66c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long private final String mSettingsActivity; 675381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme 68640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme public AutofillServiceInfo(PackageManager pm, ComponentName comp, int userHandle) 694b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long throws PackageManager.NameNotFoundException { 704b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long this(pm, getServiceInfoOrThrow(comp, userHandle)); 714b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long } 724b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long 73640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme public AutofillServiceInfo(PackageManager pm, ServiceInfo si) { 74c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long mServiceInfo = si; 750f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov final TypedArray metaDataArray = getMetaDataArray(pm, si); 76c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long if (metaDataArray != null) { 77f78e952d8df7074aa7380c5998826a4dffe335e7Felipe Leme mSettingsActivity = metaDataArray 78f78e952d8df7074aa7380c5998826a4dffe335e7Felipe Leme .getString(R.styleable.AutofillService_settingsActivity); 79c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long metaDataArray.recycle(); 80c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long } else { 81c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long mSettingsActivity = null; 82c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long } 83c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long } 84c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long 85c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long /** 86decd887f012f0c39bba855c8878eb5d8255595c4Felipe Leme * Gets the meta-data as a {@link TypedArray}, or {@code null} if not provided, 87decd887f012f0c39bba855c8878eb5d8255595c4Felipe Leme * or throws if invalid. 88c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long */ 89c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long @Nullable 900f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) { 91c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long // Check for permissions. 92decd887f012f0c39bba855c8878eb5d8255595c4Felipe Leme // TODO(b/37563972): remove support to BIND_AUTOFILL once clients use BIND_AUTOFILL_SERVICE 93decd887f012f0c39bba855c8878eb5d8255595c4Felipe Leme if (!Manifest.permission.BIND_AUTOFILL_SERVICE.equals(si.permission) 94decd887f012f0c39bba855c8878eb5d8255595c4Felipe Leme && !Manifest.permission.BIND_AUTOFILL.equals(si.permission)) { 95decd887f012f0c39bba855c8878eb5d8255595c4Felipe Leme Log.w(TAG, "AutofillService from '" + si.packageName + "' does not require permission " 96decd887f012f0c39bba855c8878eb5d8255595c4Felipe Leme + Manifest.permission.BIND_AUTOFILL_SERVICE); 97decd887f012f0c39bba855c8878eb5d8255595c4Felipe Leme throw new SecurityException("Service does not require permission " 98decd887f012f0c39bba855c8878eb5d8255595c4Felipe Leme + Manifest.permission.BIND_AUTOFILL_SERVICE); 995381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme } 1005381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme 101c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long // Get the AutoFill metadata, if declared. 102640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme XmlResourceParser parser = si.loadXmlMetaData(pm, AutofillService.SERVICE_META_DATA); 103c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long if (parser == null) { 104c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long return null; 105c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long } 106c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long 107c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long // Parse service info and get the <autofill-service> tag as an AttributeSet. 108c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long AttributeSet attrs; 1094b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long try { 110c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long // Move the XML parser to the first tag. 111c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long try { 112c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long int type; 113c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 114c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long && type != XmlPullParser.START_TAG) { 115c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long } 116c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long } catch (XmlPullParserException | IOException e) { 1170f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov Log.e(TAG, "Error parsing auto fill service meta-data", e); 1180f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov return null; 1194b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long } 1205381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme 121c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long if (!"autofill-service".equals(parser.getName())) { 1220f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov Log.e(TAG, "Meta-data does not start with autofill-service tag"); 1230f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov return null; 1244b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long } 125c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long attrs = Xml.asAttributeSet(parser); 126c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long 127c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long // Get resources required to read the AttributeSet. 128c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long Resources res; 129c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long try { 130c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long res = pm.getResourcesForApplication(si.applicationInfo); 131c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long } catch (PackageManager.NameNotFoundException e) { 1320f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov Log.e(TAG, "Error getting application resources", e); 1330f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov return null; 1344b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long } 1354b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long 136f78e952d8df7074aa7380c5998826a4dffe335e7Felipe Leme return res.obtainAttributes(attrs, R.styleable.AutofillService); 1374b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long } finally { 138c121dda89a0df1c174d63fa9c50f8924365fefe4Jason Long parser.close(); 1394b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long } 1405381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme } 1415381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme 1425381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme public ServiceInfo getServiceInfo() { 1435381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme return mServiceInfo; 1445381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme } 1454b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long 1464b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long @Nullable 1474b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long public String getSettingsActivity() { 1484b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long return mSettingsActivity; 1494b93f46130ab9a972773ebf2be9839109d5c6a08Jason Long } 1505381aa4b585f3fa2a315d88e910111173e2ef77dFelipe Leme} 151