RegisteredComponentCache.java revision 525c260303268a83da4c3413b953d13c9084e834
124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton/* 224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * Copyright (C) 2009 The Android Open Source Project 324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * 424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * you may not use this file except in compliance with the License. 624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * You may obtain a copy of the License at 724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * 824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * 1024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * Unless required by applicable law or agreed to in writing, software 1124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 1224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * See the License for the specific language governing permissions and 1424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * limitations under the License. 1524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton */ 1624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 1724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonpackage com.android.nfc; 1824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 1924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport org.xmlpull.v1.XmlPullParser; 2024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport org.xmlpull.v1.XmlPullParserException; 2124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 22525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectimport android.app.ActivityManager; 2324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.BroadcastReceiver; 2424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.Context; 2524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.Intent; 2624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.IntentFilter; 2724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.pm.ActivityInfo; 2824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.pm.PackageManager; 2924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.pm.ResolveInfo; 3024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.pm.PackageManager.NameNotFoundException; 3124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.res.Resources; 3224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.res.XmlResourceParser; 33525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectimport android.os.UserHandle; 3424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.util.Log; 3524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 3624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.io.IOException; 3724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.ArrayList; 3824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.List; 3924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.concurrent.atomic.AtomicReference; 4024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 4124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton/** 4224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * A cache of intent filters registered to receive the TECH_DISCOVERED dispatch. 4324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton */ 4424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonpublic class RegisteredComponentCache { 4524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton private static final String TAG = "RegisteredComponentCache"; 4624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 4724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton final Context mContext; 4824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton final String mAction; 4924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton final String mMetaDataName; 5024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton final AtomicReference<BroadcastReceiver> mReceiver; 5124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 5224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // synchronized on this 5324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton private ArrayList<ComponentInfo> mComponents; 5424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 5524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton public RegisteredComponentCache(Context context, String action, String metaDataName) { 5624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton mContext = context; 5724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton mAction = action; 5824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton mMetaDataName = metaDataName; 5924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 6024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton generateComponentsList(); 6124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 6224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton final BroadcastReceiver receiver = new BroadcastReceiver() { 6324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton @Override 6424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton public void onReceive(Context context1, Intent intent) { 6524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton generateComponentsList(); 6624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 6724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton }; 6824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton mReceiver = new AtomicReference<BroadcastReceiver>(receiver); 6924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter intentFilter = new IntentFilter(); 7024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 7124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 7224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 7324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton intentFilter.addDataScheme("package"); 74525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiverAsUser(receiver, UserHandle.ALL, intentFilter, null, null); 7524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Register for events related to sdcard installation. 7624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter sdFilter = new IntentFilter(); 7724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 7824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 79525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiverAsUser(receiver, UserHandle.ALL, sdFilter, null, null); 80525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Generate a new list upon switching users as well 81525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project IntentFilter userFilter = new IntentFilter(); 82525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project userFilter.addAction(Intent.ACTION_USER_SWITCHED); 83525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiverAsUser(receiver, UserHandle.ALL, userFilter, null, null); 8424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 8524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 8624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton public static class ComponentInfo { 8724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton public final ResolveInfo resolveInfo; 8824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton public final String[] techs; 8924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 9024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton ComponentInfo(ResolveInfo resolveInfo, String[] techs) { 9124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton this.resolveInfo = resolveInfo; 9224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton this.techs = techs; 9324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 9424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 9524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton @Override 9624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton public String toString() { 9724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton StringBuilder out = new StringBuilder("ComponentInfo: "); 9824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton out.append(resolveInfo); 9924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton out.append(", techs: "); 10024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton for (String tech : techs) { 10124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton out.append(tech); 10224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton out.append(", "); 10324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 10424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton return out.toString(); 10524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 10624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 10724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 10824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton /** 10924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * @return a collection of {@link RegisteredComponentCache.ComponentInfo} objects for all 11024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * registered authenticators. 11124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton */ 11224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton public ArrayList<ComponentInfo> getComponents() { 11324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton synchronized (this) { 11424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // It's safe to return a reference here since mComponents is always replaced and 11524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // never updated when it changes. 11624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton return mComponents; 11724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 11824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 11924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 12024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton /** 12124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton * Stops the monitoring of package additions, removals and changes. 12224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton */ 12324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton public void close() { 12424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton final BroadcastReceiver receiver = mReceiver.getAndSet(null); 12524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (receiver != null) { 12624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton mContext.unregisterReceiver(receiver); 12724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 12824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 12924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 13024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton @Override 13124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton protected void finalize() throws Throwable { 13224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (mReceiver.get() != null) { 13324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton Log.e(TAG, "RegisteredServicesCache finalized without being closed"); 13424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 13524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton close(); 13624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton super.finalize(); 13724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 13824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 13924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton void dump(ArrayList<ComponentInfo> components) { 14024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton for (ComponentInfo component : components) { 14124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton Log.i(TAG, component.toString()); 14224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 14324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 14424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 14524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton void generateComponentsList() { 146525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PackageManager pm; 147525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 148525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser()); 149525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project pm = mContext.createPackageContextAsUser("android", 0, 150525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project currentUser).getPackageManager(); 151525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (NameNotFoundException e) { 152525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.e(TAG, "Could not create user package context"); 153525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return; 154525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 15524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton ArrayList<ComponentInfo> components = new ArrayList<ComponentInfo>(); 156525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project List<ResolveInfo> resolveInfos = pm.queryIntentActivitiesAsUser(new Intent(mAction), 157525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PackageManager.GET_META_DATA, ActivityManager.getCurrentUser()); 15824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton for (ResolveInfo resolveInfo : resolveInfos) { 15924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton try { 160525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project parseComponentInfo(pm, resolveInfo, components); 16124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } catch (XmlPullParserException e) { 16224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton Log.w(TAG, "Unable to load component info " + resolveInfo.toString(), e); 16324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } catch (IOException e) { 16424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton Log.w(TAG, "Unable to load component info " + resolveInfo.toString(), e); 16524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 16624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 16724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 16824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton dump(components); 16924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 17024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton synchronized (this) { 17124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton mComponents = components; 17224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 17324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 17424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 175525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project void parseComponentInfo(PackageManager pm, ResolveInfo info, 176525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ArrayList<ComponentInfo> components) throws XmlPullParserException, IOException { 17724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton ActivityInfo ai = info.activityInfo; 17824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 17924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton XmlResourceParser parser = null; 18024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton try { 18124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton parser = ai.loadXmlMetaData(pm, mMetaDataName); 18224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (parser == null) { 18324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton throw new XmlPullParserException("No " + mMetaDataName + " meta-data"); 18424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 18524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 18624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton parseTechLists(pm.getResourcesForApplication(ai.applicationInfo), ai.packageName, 18724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton parser, info, components); 18824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } catch (NameNotFoundException e) { 18924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton throw new XmlPullParserException("Unable to load resources for " + ai.packageName); 19024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } finally { 19124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (parser != null) parser.close(); 19224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 19324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 19424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 19524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton void parseTechLists(Resources res, String packageName, XmlPullParser parser, 19624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton ResolveInfo resolveInfo, ArrayList<ComponentInfo> components) 19724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton throws XmlPullParserException, IOException { 19824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton int eventType = parser.getEventType(); 19924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton while (eventType != XmlPullParser.START_TAG) { 20024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton eventType = parser.next(); 20124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 20224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 203c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly ArrayList<String> items = new ArrayList<String>(); 20424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String tagName; 20524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton eventType = parser.next(); 20624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton do { 20724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton tagName = parser.getName(); 20824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (eventType == XmlPullParser.START_TAG && "tech".equals(tagName)) { 20924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton items.add(parser.nextText()); 21024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } else if (eventType == XmlPullParser.END_TAG && "tech-list".equals(tagName)) { 21124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton int size = items.size(); 21224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (size > 0) { 21324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[] techs = new String[size]; 21424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techs = items.toArray(techs); 21524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton items.clear(); 21624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton components.add(new ComponentInfo(resolveInfo, techs)); 21724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 21824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 21924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton eventType = parser.next(); 22024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } while (eventType != XmlPullParser.END_DOCUMENT); 22124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 22224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton} 223