1/*
2 * Copyright (C) 2015 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 */
16
17package com.android.statementservice.retriever;
18
19import android.content.Context;
20import android.content.pm.ApplicationInfo;
21import android.content.pm.PackageInfo;
22import android.content.pm.PackageManager;
23import android.content.pm.PackageManager.NameNotFoundException;
24import android.content.res.Resources.NotFoundException;
25
26import java.util.Arrays;
27import java.util.Collections;
28import java.util.List;
29
30/**
31 * Class that provides information about an android app from {@link PackageManager}.
32 *
33 * Visible for testing.
34 *
35 * @hide
36 */
37public class AndroidPackageInfoFetcher {
38
39    /**
40     * The name of the metadata tag in AndroidManifest.xml that stores the associated asset array
41     * ID. The metadata tag should use the android:resource attribute to point to an array resource
42     * that contains the associated assets.
43     */
44    private static final String ASSOCIATED_ASSETS_KEY = "associated_assets";
45
46    private Context mContext;
47
48    public AndroidPackageInfoFetcher(Context context) {
49        mContext = context;
50    }
51
52    /**
53     * Returns the Sha-256 fingerprints of all certificates from the specified package as a list of
54     * upper case HEX Strings with bytes separated by colons. Given an app {@link
55     * android.content.pm.Signature}, the fingerprint can be computed as {@link
56     * Utils#computeNormalizedSha256Fingerprint} {@code(signature.toByteArray())}.
57     *
58     * <p>Given a signed APK, Java 7's commandline keytool can compute the fingerprint using: {@code
59     * keytool -list -printcert -jarfile signed_app.apk}
60     *
61     * <p>Example: "10:39:38:EE:45:37:E5:9E:8E:E7:92:F6:54:50:4F:B8:34:6F:C6:B3:46:D0:BB:C4:41:5F:C3:39:FC:FC:8E:C1"
62     *
63     * @throws NameNotFoundException if an app with packageName is not installed on the device.
64     */
65    public List<String> getCertFingerprints(String packageName) throws NameNotFoundException {
66        return Utils.getCertFingerprintsFromPackageManager(packageName, mContext);
67    }
68
69    /**
70     * Returns all statements that the specified package makes in its AndroidManifest.xml.
71     *
72     * @throws NameNotFoundException if the app is not installed on the device.
73     */
74    public List<String> getStatements(String packageName) throws NameNotFoundException {
75        PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(
76                packageName, PackageManager.GET_META_DATA);
77        ApplicationInfo appInfo = packageInfo.applicationInfo;
78        if (appInfo.metaData == null) {
79            return Collections.<String>emptyList();
80        }
81        int tokenResourceId = appInfo.metaData.getInt(ASSOCIATED_ASSETS_KEY);
82        if (tokenResourceId == 0) {
83            return Collections.<String>emptyList();
84        }
85        try {
86            return Arrays.asList(
87                    mContext.getPackageManager().getResourcesForApplication(packageName)
88                    .getStringArray(tokenResourceId));
89        } catch (NotFoundException e) {
90            return Collections.<String>emptyList();
91        }
92    }
93}
94