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