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