1 /*
2  * Copyright (C) 2013 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 package com.android.tradefed.device;
17 
18 import java.util.HashMap;
19 import java.util.Map;
20 
21 /**
22  * Container for an application's package info parsed from device.
23  */
24 public class PackageInfo {
25 
26     // numeric flag constants. Copied from
27     // frameworks/base/core/java/android/content/pm/ApplicationInfo.java
28     private static final int FLAG_UPDATED_SYSTEM_APP = 1 << 7;
29     private static final int FLAG_SYSTEM = 1 << 0;
30     public static final int FLAG_PERSISTENT = 1 << 3;
31 
32     // string flag constants. Used for newer platforms
33     private static final String FLAG_UPDATED_SYSTEM_APP_TEXT = " UPDATED_SYSTEM_APP ";
34     private static final String FLAG_SYSTEM_TEXT = " SYSTEM ";
35     private static final String FLAG_PERSISTENT_TEXT = " PERSISTENT ";
36 
37     private final String mPackageName;
38     private boolean mIsSystemApp;
39     private boolean mIsUpdatedSystemApp;
40     private boolean mIsPersistentApp;
41     private Map<String, String> mAttributes = new HashMap<String, String>();
42     private Map<Integer, String> mPerUserFirstInstallTime = new HashMap<>();
43 
PackageInfo(String pkgName)44     PackageInfo(String pkgName) {
45         mPackageName = pkgName;
46     }
47 
48     /**
49      * Returns <code>true</code> if this is a system app that has been updated.
50      */
isUpdatedSystemApp()51     public boolean isUpdatedSystemApp() {
52         return mIsUpdatedSystemApp;
53     }
54 
55     /**
56      * Returns <code>true</code> if this is a system app.
57      */
isSystemApp()58     public boolean isSystemApp() {
59         return mIsSystemApp;
60     }
61 
62     /**
63      * Returns <code>true</code> if this is a persistent app.
64      */
isPersistentApp()65     public boolean isPersistentApp() {
66         return mIsPersistentApp;
67     }
68 
69     /**
70      * Returns the package name of the application.
71      */
getPackageName()72     public String getPackageName() {
73         return mPackageName;
74     }
75 
76     /**
77      * Returns the version name of the application.
78      * Note: this will return <code>null</code> if 'versionName' attribute was not found, such as
79      * on froyo devices.
80      */
getVersionName()81     public String getVersionName() {
82         return mAttributes.get("versionName");
83     }
84 
85     /**
86      * Returns the version name of the application. Note: this will return <code>null</code> if
87      * 'versionCode' attribute was not found
88      */
getVersionCode()89     public String getVersionCode() {
90         return mAttributes.get("versionCode");
91     }
92 
93     /** Returns where the package is located in the filesystem. */
getCodePath()94     public String getCodePath() {
95         return mAttributes.get("codePath");
96     }
97 
setIsUpdatedSystemApp(boolean isUpdatedSystemApp)98     void setIsUpdatedSystemApp(boolean isUpdatedSystemApp) {
99         mIsUpdatedSystemApp = isUpdatedSystemApp;
100     }
101 
addAttribute(String name, String value)102     void addAttribute(String name, String value) {
103         mAttributes.put(name, value);
104         if (name.equals("pkgFlags") || name.equals("flags")) {
105             // do special handling of pkgFlags, which can be either hex or string form depending on
106             // device OS version
107             if (!parseFlagsAsInt(value)) {
108                 parseFlagsAsString(value);
109             }
110         }
111     }
112 
parseFlagsAsString(String flagString)113     private void parseFlagsAsString(String flagString) {
114         mIsSystemApp = flagString.contains(FLAG_SYSTEM_TEXT);
115         mIsUpdatedSystemApp = flagString.contains(FLAG_UPDATED_SYSTEM_APP_TEXT);
116         mIsPersistentApp = flagString.contains(FLAG_PERSISTENT_TEXT);
117     }
118 
parseFlagsAsInt(String value)119     private boolean parseFlagsAsInt(String value) {
120         try {
121             int flags =  Integer.decode(value);
122             mIsSystemApp = (flags & FLAG_SYSTEM) != 0;
123             // note: FLAG_UPDATED_SYSTEM_APP never seems to be set. Rely on parsing hidden system
124             // packages
125             mIsUpdatedSystemApp = (flags & FLAG_UPDATED_SYSTEM_APP) != 0;
126             mIsPersistentApp = (flags & FLAG_PERSISTENT) != 0;
127             return true;
128         } catch (NumberFormatException e) {
129             // not an int, fall through
130         }
131         return false;
132     }
133 
addPerUserAttribute(int userId, String attr, String value)134     public void addPerUserAttribute(int userId, String attr, String value) {
135         if (!attr.equals("firstInstallTime")) {
136             return;
137         }
138         mPerUserFirstInstallTime.put(userId, value);
139     }
140 
getFirstInstallTime(int userId)141     public String getFirstInstallTime(int userId) {
142         return mPerUserFirstInstallTime.get(userId);
143     }
144 }
145