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 
17 package com.android.statementservice.retriever;
18 
19 import android.content.Context;
20 import android.content.pm.ApplicationInfo;
21 import android.content.pm.PackageInfo;
22 import android.content.pm.PackageManager;
23 import android.content.pm.PackageManager.NameNotFoundException;
24 import android.content.res.Resources.NotFoundException;
25 
26 import java.util.Arrays;
27 import java.util.Collections;
28 import 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  */
37 public 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 
AndroidPackageInfoFetcher(Context context)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      */
getCertFingerprints(String packageName)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      */
getStatements(String packageName)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