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 package com.android.car.pm;
17 
18 import android.annotation.Nullable;
19 import android.content.Context;
20 import android.content.pm.ActivityInfo;
21 import android.content.pm.PackageInfo;
22 import android.content.pm.PackageManager;
23 import android.content.pm.PackageManager.NameNotFoundException;
24 import android.os.Bundle;
25 import android.util.Log;
26 
27 import com.android.car.CarLog;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 /**
33  *  Read App meta data and look for Distraction Optimization(DO) tags.
34  *  An app can tag a distraction optimized activity to be DO by adding the following meta-data
35  *  to that <activity> element:
36  *
37  *  <pre>{@code
38  *  <activity>
39  *      <meta-data android:name="distractionOptimized" android:value="true"/>
40  *  </activity>
41  *  }</pre>
42  *
43  */
44 public class CarAppMetadataReader {
45     /** Name of the meta-data attribute of the Activity that denotes distraction optimized */
46     private static final String DO_METADATA_ATTRIBUTE = "distractionOptimized";
47 
48     /**
49      * Parses the given package and returns Distraction Optimized information, if present.
50      *
51      * @return Array of DO activity names in the given package
52      */
53     @Nullable
findDistractionOptimizedActivitiesAsUser(Context context, String packageName, int userId)54     public static String[] findDistractionOptimizedActivitiesAsUser(Context context,
55             String packageName, int userId) throws NameNotFoundException {
56         final PackageManager pm = context.getPackageManager();
57 
58         // Check if any of the activities in the package are DO by checking all the
59         // <activity> elements. MATCH_DISABLED_COMPONENTS is included so that we are immediately
60         // prepared to respond to any components that toggle from disabled to enabled.
61         PackageInfo pkgInfo =
62                 pm.getPackageInfoAsUser(
63                         packageName, PackageManager.GET_ACTIVITIES
64                                 | PackageManager.GET_META_DATA
65                                 | PackageManager.MATCH_DISABLED_COMPONENTS
66                                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
67                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
68                         userId);
69         if (pkgInfo == null) {
70             return null;
71         }
72 
73         ActivityInfo[] activities = pkgInfo.activities;
74         if (activities == null) {
75             if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.DEBUG)) {
76                 Log.d(CarLog.TAG_PACKAGE, "Null Activities for " + packageName);
77             }
78             return null;
79         }
80         List<String> optimizedActivityList = new ArrayList();
81         for (ActivityInfo activity : activities) {
82             Bundle mData = activity.metaData;
83             if (mData != null && mData.getBoolean(DO_METADATA_ATTRIBUTE, false)) {
84                 if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.DEBUG)) {
85                     Log.d(CarLog.TAG_PACKAGE,
86                             "DO Activity:" + activity.packageName + "/" + activity.name);
87                 }
88                 optimizedActivityList.add(activity.name);
89             }
90         }
91         if (optimizedActivityList.isEmpty()) {
92             return null;
93         }
94         return optimizedActivityList.toArray(new String[optimizedActivityList.size()]);
95     }
96 }
97