Loading AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ <uses-permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES" /> <uses-permission android:name="android.permission.QUERY_ADMIN_POLICY" /> <uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" /> <uses-permission android:name="android.permission.START_VIEW_APP_FEATURES" /> <application android:name=".SettingsApplication" Loading res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -13543,6 +13543,9 @@ <!-- Summary for extra app info settings for a specific app [CHAR LIMIT=40] --> <string name="extra_app_info_summary" translatable="false"></string> <!-- Label for All Services preference in App info settings [CHAR LIMIT=40] --> <string name="app_info_all_services_label">All Services</string> <!-- Title for toggle controlling whether notifications are shown when an app pastes from clipboard. [CHAR LIMIT=50] --> <string name="show_clip_access_notification">Show clipboard access</string> res/xml/app_info_settings.xml +6 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,12 @@ android:title="@string/app_settings_link" settings:controller="com.android.settings.applications.appinfo.AppSettingPreferenceController" /> <Preference android:key="all_services_settings" android:title="@string/app_info_all_services_label" android:summary="@string/summary_placeholder" settings:controller="com.android.settings.applications.appinfo.AppAllServicesPreferenceController" /> <Preference android:key="notification_settings" android:title="@string/notifications_label" Loading src/com/android/settings/applications/appinfo/AppAllServicesPreferenceController.java 0 → 100644 +168 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.applications.appinfo; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import java.util.Objects; /** * Preference Controller for the "All Services" preference in the "App Info" page. */ public class AppAllServicesPreferenceController extends AppInfoPreferenceControllerBase { private static final String TAG = "AllServicesPrefControl"; private static final String SUMMARY_METADATA_KEY = "app_features_preference_summary"; private final PackageManager mPackageManager; private String mPackageName; private boolean mCanPackageHandleAllServicesIntent; private boolean mIsLocationProvider; public AppAllServicesPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); mPackageManager = context.getPackageManager(); // Set to false till we can confirm that the package can handle the intent. mCanPackageHandleAllServicesIntent = false; // Set to false till we can confirm that the package is a location provider. mIsLocationProvider = false; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); CharSequence summary = getStorageSummary(); if (summary != null) { mPreference.setSummary(summary); } } @VisibleForTesting @Nullable CharSequence getStorageSummary() { ResolveInfo resolveInfo = getResolveInfo(PackageManager.GET_META_DATA); if (resolveInfo == null) { Log.d(TAG, "mResolveInfo is null."); return null; } final Bundle metaData = resolveInfo.activityInfo.metaData; if (metaData != null) { try { final Resources pkgRes = mPackageManager.getResourcesForActivity( new ComponentName(mPackageName, resolveInfo.activityInfo.name)); return pkgRes.getString(metaData.getInt(SUMMARY_METADATA_KEY)); } catch (Resources.NotFoundException exception) { Log.d(TAG, "Resource not found for summary string."); } catch (PackageManager.NameNotFoundException exception) { Log.d(TAG, "Name of resource not found for summary string."); } } return null; } @Override public int getAvailabilityStatus() { if (mCanPackageHandleAllServicesIntent && mIsLocationProvider) { return AVAILABLE; } return CONDITIONALLY_UNAVAILABLE; } private boolean isLocationProvider() { return Objects.requireNonNull( mContext.getSystemService(LocationManager.class)).isProviderPackage(mPackageName); } private boolean canPackageHandleIntent() { return getResolveInfo(0) != null; } @Override public boolean handlePreferenceTreeClick(Preference preference) { if (getPreferenceKey().equals(preference.getKey())) { startAllServicesActivity(); return true; } return false; } /** * Set the package name of the package for which the "All Services" activity needs to be shown. * * @param packageName Name of the package for which the services need to be shown. */ public void setPackageName(String packageName) { mPackageName = packageName; //Once we have package name. Update conditions for availability. updateAvailabilityConditions(); } private void updateAvailabilityConditions() { mCanPackageHandleAllServicesIntent = canPackageHandleIntent(); mIsLocationProvider = isLocationProvider(); } private void startAllServicesActivity() { final Intent featuresIntent = new Intent(Intent.ACTION_VIEW_APP_FEATURES); // This won't be null since the preference is only shown for packages that can handle the // intent. ResolveInfo resolveInfo = getResolveInfo(0); featuresIntent.setComponent( new ComponentName(mPackageName, resolveInfo.activityInfo.name)); Activity activity = mParent.getActivity(); try { if (activity != null) { activity.startActivity(featuresIntent); } } catch (ActivityNotFoundException e) { Log.e(TAG, "The app cannot handle android.intent.action.VIEW_APP_FEATURES"); } } @Nullable private ResolveInfo getResolveInfo(int flags) { if (mPackageName == null) { return null; } final Intent featuresIntent = new Intent(Intent.ACTION_VIEW_APP_FEATURES); featuresIntent.setPackage(mPackageName); return mPackageManager.resolveActivity(featuresIntent, flags); } } src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +2 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,8 @@ public class AppInfoDashboardFragment extends DashboardFragment use(AppSettingPreferenceController.class) .setPackageName(packageName) .setParentFragment(this); use(AppAllServicesPreferenceController.class).setParentFragment(this); use(AppAllServicesPreferenceController.class).setPackageName(packageName); use(AppStoragePreferenceController.class).setParentFragment(this); use(AppVersionPreferenceController.class).setParentFragment(this); use(InstantAppDomainsPreferenceController.class).setParentFragment(this); Loading Loading
AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ <uses-permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES" /> <uses-permission android:name="android.permission.QUERY_ADMIN_POLICY" /> <uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" /> <uses-permission android:name="android.permission.START_VIEW_APP_FEATURES" /> <application android:name=".SettingsApplication" Loading
res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -13543,6 +13543,9 @@ <!-- Summary for extra app info settings for a specific app [CHAR LIMIT=40] --> <string name="extra_app_info_summary" translatable="false"></string> <!-- Label for All Services preference in App info settings [CHAR LIMIT=40] --> <string name="app_info_all_services_label">All Services</string> <!-- Title for toggle controlling whether notifications are shown when an app pastes from clipboard. [CHAR LIMIT=50] --> <string name="show_clip_access_notification">Show clipboard access</string>
res/xml/app_info_settings.xml +6 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,12 @@ android:title="@string/app_settings_link" settings:controller="com.android.settings.applications.appinfo.AppSettingPreferenceController" /> <Preference android:key="all_services_settings" android:title="@string/app_info_all_services_label" android:summary="@string/summary_placeholder" settings:controller="com.android.settings.applications.appinfo.AppAllServicesPreferenceController" /> <Preference android:key="notification_settings" android:title="@string/notifications_label" Loading
src/com/android/settings/applications/appinfo/AppAllServicesPreferenceController.java 0 → 100644 +168 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.applications.appinfo; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import java.util.Objects; /** * Preference Controller for the "All Services" preference in the "App Info" page. */ public class AppAllServicesPreferenceController extends AppInfoPreferenceControllerBase { private static final String TAG = "AllServicesPrefControl"; private static final String SUMMARY_METADATA_KEY = "app_features_preference_summary"; private final PackageManager mPackageManager; private String mPackageName; private boolean mCanPackageHandleAllServicesIntent; private boolean mIsLocationProvider; public AppAllServicesPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); mPackageManager = context.getPackageManager(); // Set to false till we can confirm that the package can handle the intent. mCanPackageHandleAllServicesIntent = false; // Set to false till we can confirm that the package is a location provider. mIsLocationProvider = false; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); CharSequence summary = getStorageSummary(); if (summary != null) { mPreference.setSummary(summary); } } @VisibleForTesting @Nullable CharSequence getStorageSummary() { ResolveInfo resolveInfo = getResolveInfo(PackageManager.GET_META_DATA); if (resolveInfo == null) { Log.d(TAG, "mResolveInfo is null."); return null; } final Bundle metaData = resolveInfo.activityInfo.metaData; if (metaData != null) { try { final Resources pkgRes = mPackageManager.getResourcesForActivity( new ComponentName(mPackageName, resolveInfo.activityInfo.name)); return pkgRes.getString(metaData.getInt(SUMMARY_METADATA_KEY)); } catch (Resources.NotFoundException exception) { Log.d(TAG, "Resource not found for summary string."); } catch (PackageManager.NameNotFoundException exception) { Log.d(TAG, "Name of resource not found for summary string."); } } return null; } @Override public int getAvailabilityStatus() { if (mCanPackageHandleAllServicesIntent && mIsLocationProvider) { return AVAILABLE; } return CONDITIONALLY_UNAVAILABLE; } private boolean isLocationProvider() { return Objects.requireNonNull( mContext.getSystemService(LocationManager.class)).isProviderPackage(mPackageName); } private boolean canPackageHandleIntent() { return getResolveInfo(0) != null; } @Override public boolean handlePreferenceTreeClick(Preference preference) { if (getPreferenceKey().equals(preference.getKey())) { startAllServicesActivity(); return true; } return false; } /** * Set the package name of the package for which the "All Services" activity needs to be shown. * * @param packageName Name of the package for which the services need to be shown. */ public void setPackageName(String packageName) { mPackageName = packageName; //Once we have package name. Update conditions for availability. updateAvailabilityConditions(); } private void updateAvailabilityConditions() { mCanPackageHandleAllServicesIntent = canPackageHandleIntent(); mIsLocationProvider = isLocationProvider(); } private void startAllServicesActivity() { final Intent featuresIntent = new Intent(Intent.ACTION_VIEW_APP_FEATURES); // This won't be null since the preference is only shown for packages that can handle the // intent. ResolveInfo resolveInfo = getResolveInfo(0); featuresIntent.setComponent( new ComponentName(mPackageName, resolveInfo.activityInfo.name)); Activity activity = mParent.getActivity(); try { if (activity != null) { activity.startActivity(featuresIntent); } } catch (ActivityNotFoundException e) { Log.e(TAG, "The app cannot handle android.intent.action.VIEW_APP_FEATURES"); } } @Nullable private ResolveInfo getResolveInfo(int flags) { if (mPackageName == null) { return null; } final Intent featuresIntent = new Intent(Intent.ACTION_VIEW_APP_FEATURES); featuresIntent.setPackage(mPackageName); return mPackageManager.resolveActivity(featuresIntent, flags); } }
src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java +2 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,8 @@ public class AppInfoDashboardFragment extends DashboardFragment use(AppSettingPreferenceController.class) .setPackageName(packageName) .setParentFragment(this); use(AppAllServicesPreferenceController.class).setParentFragment(this); use(AppAllServicesPreferenceController.class).setPackageName(packageName); use(AppStoragePreferenceController.class).setParentFragment(this); use(AppVersionPreferenceController.class).setParentFragment(this); use(InstantAppDomainsPreferenceController.class).setParentFragment(this); Loading