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.settings.applications.appinfo; 18 19 import android.app.Activity; 20 import android.content.ActivityNotFoundException; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.pm.PackageManager; 25 import android.content.pm.ResolveInfo; 26 import android.content.res.Resources; 27 import android.location.LocationManager; 28 import android.os.Bundle; 29 import android.util.Log; 30 31 import androidx.annotation.Nullable; 32 import androidx.annotation.VisibleForTesting; 33 import androidx.preference.Preference; 34 import androidx.preference.PreferenceScreen; 35 36 import java.util.Objects; 37 38 /** 39 * Preference Controller for the "All Services" preference in the "App Info" page. 40 */ 41 public class AppAllServicesPreferenceController extends AppInfoPreferenceControllerBase { 42 43 private static final String TAG = "AllServicesPrefControl"; 44 private static final String SUMMARY_METADATA_KEY = "app_features_preference_summary"; 45 46 private final PackageManager mPackageManager; 47 48 private String mPackageName; 49 AppAllServicesPreferenceController(Context context, String preferenceKey)50 public AppAllServicesPreferenceController(Context context, 51 String preferenceKey) { 52 super(context, preferenceKey); 53 mPackageManager = context.getPackageManager(); 54 } 55 56 @Override displayPreference(PreferenceScreen screen)57 public void displayPreference(PreferenceScreen screen) { 58 super.displayPreference(screen); 59 CharSequence summary = getStorageSummary(); 60 if (summary != null) { 61 mPreference.setSummary(summary); 62 } 63 } 64 65 @Nullable getStorageSummary()66 private CharSequence getStorageSummary() { 67 ResolveInfo resolveInfo = getResolveInfo(PackageManager.GET_META_DATA); 68 if (resolveInfo == null) { 69 Log.d(TAG, "mResolveInfo is null."); 70 return null; 71 } 72 final Bundle metaData = resolveInfo.activityInfo.metaData; 73 if (metaData != null) { 74 try { 75 final Resources pkgRes = mPackageManager.getResourcesForActivity( 76 new ComponentName(mPackageName, resolveInfo.activityInfo.name)); 77 return pkgRes.getString(metaData.getInt(SUMMARY_METADATA_KEY)); 78 } catch (Resources.NotFoundException exception) { 79 Log.d(TAG, "Resource not found for summary string."); 80 } catch (PackageManager.NameNotFoundException exception) { 81 Log.d(TAG, "Name of resource not found for summary string."); 82 } 83 } 84 return null; 85 } 86 87 @Override getAvailabilityStatus()88 public int getAvailabilityStatus() { 89 if (canPackageHandleIntent() && isLocationProvider()) { 90 return AVAILABLE; 91 } 92 return CONDITIONALLY_UNAVAILABLE; 93 } 94 95 @VisibleForTesting isLocationProvider()96 boolean isLocationProvider() { 97 return Objects.requireNonNull( 98 mContext.getSystemService(LocationManager.class)).isProviderPackage(mPackageName); 99 } 100 101 @VisibleForTesting canPackageHandleIntent()102 boolean canPackageHandleIntent() { 103 return getResolveInfo(0) != null; 104 } 105 106 @Override handlePreferenceTreeClick(Preference preference)107 public boolean handlePreferenceTreeClick(Preference preference) { 108 if (getPreferenceKey().equals(preference.getKey())) { 109 startAllServicesActivity(); 110 return true; 111 } 112 return false; 113 } 114 115 /** 116 * Set the package name of the package for which the "All Services" activity needs to be shown. 117 * 118 * @param packageName Name of the package for which the services need to be shown. 119 */ setPackageName(String packageName)120 public void setPackageName(String packageName) { 121 mPackageName = packageName; 122 } 123 startAllServicesActivity()124 private void startAllServicesActivity() { 125 final Intent featuresIntent = new Intent(Intent.ACTION_VIEW_APP_FEATURES); 126 // This won't be null since the preference is only shown for packages that can handle the 127 // intent. 128 ResolveInfo resolveInfo = getResolveInfo(0); 129 featuresIntent.setComponent( 130 new ComponentName(mPackageName, resolveInfo.activityInfo.name)); 131 132 Activity activity = mParent.getActivity(); 133 try { 134 if (activity != null) { 135 activity.startActivity(featuresIntent); 136 } 137 } catch (ActivityNotFoundException e) { 138 Log.e(TAG, "The app cannot handle android.intent.action.VIEW_APP_FEATURES"); 139 } 140 } 141 142 @Nullable getResolveInfo(int flags)143 private ResolveInfo getResolveInfo(int flags) { 144 if (mPackageName == null) { 145 return null; 146 } 147 final Intent featuresIntent = new Intent(Intent.ACTION_VIEW_APP_FEATURES); 148 featuresIntent.setPackage(mPackageName); 149 150 return mPackageManager.resolveActivity(featuresIntent, flags); 151 } 152 } 153