1 /* 2 * Copyright (C) 2022 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.ondevicepersonalization.services.manifest; 18 19 import android.content.Context; 20 import android.content.pm.PackageManager; 21 import android.content.res.Resources; 22 import android.content.res.XmlResourceParser; 23 24 /** 25 * Helper class for parsing and checking app manifest configs 26 */ 27 public final class AppManifestConfigHelper { 28 private static final String ON_DEVICE_PERSONALIZATION_CONFIG_PROPERTY = 29 "android.ondevicepersonalization.ON_DEVICE_PERSONALIZATION_CONFIG"; 30 AppManifestConfigHelper()31 private AppManifestConfigHelper() { 32 } 33 34 /** 35 * Determines if the given package's manifest contains ODP settings 36 * 37 * @param context the context of the API call. 38 * @param packageName the packageName of the package whose manifest config will be read 39 * @return true if the ODP setting exists, false otherwise 40 */ manifestContainsOdpSettings(Context context, String packageName)41 public static Boolean manifestContainsOdpSettings(Context context, 42 String packageName) { 43 PackageManager pm = context.getPackageManager(); 44 try { 45 pm.getProperty(ON_DEVICE_PERSONALIZATION_CONFIG_PROPERTY, packageName); 46 } catch (PackageManager.NameNotFoundException e) { 47 return false; 48 } 49 return true; 50 } 51 getAppManifestConfig(Context context, String packageName)52 static AppManifestConfig getAppManifestConfig(Context context, 53 String packageName) { 54 if (!manifestContainsOdpSettings(context, packageName)) { 55 // TODO(b/241941021) Determine correct exception to throw 56 throw new IllegalArgumentException( 57 "OdpSettings not found for package: " + packageName.toString()); 58 } 59 PackageManager pm = context.getPackageManager(); 60 try { 61 int resId = pm.getProperty(ON_DEVICE_PERSONALIZATION_CONFIG_PROPERTY, 62 packageName).getResourceId(); 63 Resources resources = pm.getResourcesForApplication(packageName); 64 XmlResourceParser xmlParser = resources.getXml(resId); 65 // TODO(b/239479120) Update to avoid re-parsing the XML too frequently if required 66 return AppManifestConfigParser.getConfig(xmlParser); 67 } catch (Exception e) { 68 // TODO(b/241941021) Determine correct exception to throw 69 throw new IllegalArgumentException( 70 "Failed to parse manifest for package: " + packageName, e); 71 } 72 } 73 74 /** 75 * Gets the download URL from package's ODP settings config 76 * 77 * @param context the context of the API call. 78 * @param packageName the packageName of the package whose manifest config will be read 79 */ getDownloadUrlFromOdpSettings(Context context, String packageName)80 public static String getDownloadUrlFromOdpSettings(Context context, String packageName) { 81 return getAppManifestConfig(context, packageName).getDownloadUrl(); 82 } 83 84 /** 85 * Gets the service name from package's ODP settings config 86 * 87 * @param context the context of the API call. 88 * @param packageName the packageName of the package whose manifest config will be read 89 */ getServiceNameFromOdpSettings(Context context, String packageName)90 public static String getServiceNameFromOdpSettings(Context context, 91 String packageName) { 92 return getAppManifestConfig(context, packageName).getServiceName(); 93 } 94 } 95