Loading AndroidManifest.xml +9 −0 Original line number Diff line number Diff line Loading @@ -4285,6 +4285,15 @@ android:value="true" /> </activity> <!-- Access to the Credential Manager list. --> <activity android:name=".applications.credentials.CredentialsPickerActivity" android:excludeFromRecents="true" android:launchMode="singleInstance" android:exported="false"> <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.applications.credentials.DefaultCombinedPicker" /> </activity> <activity android:name=".Settings$SystemDashboardActivity" android:label="@string/header_category_system" Loading src/com/android/settings/applications/credentials/CombinedProviderInfo.java +31 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,37 @@ public final class CombinedProviderInfo { return mAutofillServiceInfo.getServiceInfo().applicationInfo; } /** Returns the package name. */ public @Nullable String getPackageName() { ApplicationInfo ai = getApplicationInfo(); if (ai != null) { return ai.packageName; } return null; } /** Returns the settings activity. */ public @Nullable String getSettingsActivity() { // This logic is not used by the top entry but rather what activity should // be launched from the settings screen. for (CredentialProviderInfo cpi : mCredentialProviderInfos) { final CharSequence settingsActivity = cpi.getSettingsActivity(); if (!TextUtils.isEmpty(settingsActivity)) { return String.valueOf(settingsActivity); } } if (mAutofillServiceInfo != null) { final String settingsActivity = mAutofillServiceInfo.getSettingsActivity(); if (!TextUtils.isEmpty(settingsActivity)) { return settingsActivity; } } return null; } /** Returns the app icon. */ @Nullable public Drawable getAppIcon(@NonNull Context context, int userId) { Loading src/com/android/settings/applications/credentials/CredentialsPickerActivity.java 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.credentials; import com.android.settings.SettingsActivity; /** Standalone activity used to launch a {@link DefaultCombinedPicker} fragment. */ public class CredentialsPickerActivity extends SettingsActivity { @Override protected boolean isValidFragment(String fragmentName) { return super.isValidFragment(fragmentName) || DefaultCombinedPicker.class.getName().equals(fragmentName); } } src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java +50 −58 Original line number Diff line number Diff line Loading @@ -16,11 +16,10 @@ package com.android.settings.applications.credentials; import android.annotation.Nullable; 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.pm.ServiceInfo; import android.credentials.CredentialManager; import android.credentials.CredentialProviderInfo; Loading @@ -29,16 +28,19 @@ import android.provider.Settings; import android.service.autofill.AutofillService; import android.service.autofill.AutofillServiceInfo; import android.text.TextUtils; import android.util.Log; import android.view.autofill.AutofillManager; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.applications.defaultapps.DefaultAppPreferenceController; import com.android.settingslib.applications.DefaultAppInfo; import java.util.ArrayList; import java.util.List; public class DefaultCombinedPreferenceController extends DefaultAppPreferenceController { public class DefaultCombinedPreferenceController extends DefaultAppPreferenceController implements Preference.OnPreferenceClickListener { private static final Intent AUTOFILL_PROBE = new Intent(AutofillService.SERVICE_INTERFACE); private static final String TAG = "DefaultCombinedPreferenceController"; Loading Loading @@ -73,18 +75,55 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon @Override protected Intent getSettingIntent(DefaultAppInfo info) { if (info == null) { return null; // Despite this method being called getSettingIntent this intent actually // opens the primary picker. This is so that we can swap the cog and the left // hand side presses to align the UX. return new Intent(mContext, CredentialsPickerActivity.class); } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); final String prefKey = getPreferenceKey(); final Preference preference = screen.findPreference(prefKey); if (preference != null) { preference.setOnPreferenceClickListener((Preference.OnPreferenceClickListener) this); } final AutofillSettingIntentProvider intentProvider = new AutofillSettingIntentProvider(mContext, getUser(), info.getKey()); return intentProvider.getIntent(); } @Override protected DefaultAppInfo getDefaultAppInfo() { public boolean onPreferenceClick(Preference preference) { // Get the selected provider. final CombinedProviderInfo topProvider = getTopProvider(); if (topProvider == null) { return false; } // If the top provider has a defined Credential Manager settings // provider then we should open that up. final String settingsActivity = topProvider.getSettingsActivity(); if (!TextUtils.isEmpty(settingsActivity)) { final Intent intent = new Intent(Intent.ACTION_MAIN) .setComponent( new ComponentName( topProvider.getPackageName(), settingsActivity)); startActivity(intent); return true; } return false; } private @Nullable CombinedProviderInfo getTopProvider() { List<CombinedProviderInfo> providers = getAllProviders(getUser()); CombinedProviderInfo topProvider = CombinedProviderInfo.getTopProvider(providers); return CombinedProviderInfo.getTopProvider(providers); } @Override protected DefaultAppInfo getDefaultAppInfo() { CombinedProviderInfo topProvider = getTopProvider(); if (topProvider != null) { ServiceInfo brandingService = topProvider.getBrandingService(); if (brandingService == null) { Loading Loading @@ -138,53 +177,6 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon return true; } /** Provides Intent to setting activity for the specified autofill service. */ static final class AutofillSettingIntentProvider { private final String mKey; private final Context mContext; private final int mUserId; public AutofillSettingIntentProvider(Context context, int userId, String key) { mKey = key; mContext = context; mUserId = userId; } public Intent getIntent() { final List<ResolveInfo> resolveInfos = mContext.getPackageManager() .queryIntentServicesAsUser( AUTOFILL_PROBE, PackageManager.GET_META_DATA, mUserId); for (ResolveInfo resolveInfo : resolveInfos) { final ServiceInfo serviceInfo = resolveInfo.serviceInfo; // If there are multiple autofill services then pick the first one. if (mKey != null && mKey.startsWith(serviceInfo.packageName)) { final String settingsActivity; try { settingsActivity = new AutofillServiceInfo(mContext, serviceInfo) .getSettingsActivity(); } catch (SecurityException e) { // Service does not declare the proper permission, ignore it. Log.e(TAG, "Error getting info for " + serviceInfo + ": " + e); return null; } if (TextUtils.isEmpty(settingsActivity)) { return null; } return new Intent(Intent.ACTION_MAIN) .setComponent( new ComponentName(serviceInfo.packageName, settingsActivity)); } } return null; } } protected int getUser() { return UserHandle.myUserId(); } Loading src/com/android/settings/applications/credentials/DefaultPrivateCombinedPreferenceController.kt +0 −9 Original line number Diff line number Diff line Loading @@ -36,15 +36,6 @@ class DefaultPrivateCombinedPreferenceController(context: Context?) : DefaultCom return "default_credman_autofill_private" } override fun getSettingIntent(info: DefaultAppInfo ?): Intent ? { if (info == null) { return null } return userHandle?.let { handle -> AutofillSettingIntentProvider(mContext, handle.identifier, info.key).intent } ?: null } override fun startActivity(intent: Intent) { userHandle?.let { handle -> mContext.startActivityAsUser(intent, handle) Loading Loading
AndroidManifest.xml +9 −0 Original line number Diff line number Diff line Loading @@ -4285,6 +4285,15 @@ android:value="true" /> </activity> <!-- Access to the Credential Manager list. --> <activity android:name=".applications.credentials.CredentialsPickerActivity" android:excludeFromRecents="true" android:launchMode="singleInstance" android:exported="false"> <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.applications.credentials.DefaultCombinedPicker" /> </activity> <activity android:name=".Settings$SystemDashboardActivity" android:label="@string/header_category_system" Loading
src/com/android/settings/applications/credentials/CombinedProviderInfo.java +31 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,37 @@ public final class CombinedProviderInfo { return mAutofillServiceInfo.getServiceInfo().applicationInfo; } /** Returns the package name. */ public @Nullable String getPackageName() { ApplicationInfo ai = getApplicationInfo(); if (ai != null) { return ai.packageName; } return null; } /** Returns the settings activity. */ public @Nullable String getSettingsActivity() { // This logic is not used by the top entry but rather what activity should // be launched from the settings screen. for (CredentialProviderInfo cpi : mCredentialProviderInfos) { final CharSequence settingsActivity = cpi.getSettingsActivity(); if (!TextUtils.isEmpty(settingsActivity)) { return String.valueOf(settingsActivity); } } if (mAutofillServiceInfo != null) { final String settingsActivity = mAutofillServiceInfo.getSettingsActivity(); if (!TextUtils.isEmpty(settingsActivity)) { return settingsActivity; } } return null; } /** Returns the app icon. */ @Nullable public Drawable getAppIcon(@NonNull Context context, int userId) { Loading
src/com/android/settings/applications/credentials/CredentialsPickerActivity.java 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.credentials; import com.android.settings.SettingsActivity; /** Standalone activity used to launch a {@link DefaultCombinedPicker} fragment. */ public class CredentialsPickerActivity extends SettingsActivity { @Override protected boolean isValidFragment(String fragmentName) { return super.isValidFragment(fragmentName) || DefaultCombinedPicker.class.getName().equals(fragmentName); } }
src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java +50 −58 Original line number Diff line number Diff line Loading @@ -16,11 +16,10 @@ package com.android.settings.applications.credentials; import android.annotation.Nullable; 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.pm.ServiceInfo; import android.credentials.CredentialManager; import android.credentials.CredentialProviderInfo; Loading @@ -29,16 +28,19 @@ import android.provider.Settings; import android.service.autofill.AutofillService; import android.service.autofill.AutofillServiceInfo; import android.text.TextUtils; import android.util.Log; import android.view.autofill.AutofillManager; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.applications.defaultapps.DefaultAppPreferenceController; import com.android.settingslib.applications.DefaultAppInfo; import java.util.ArrayList; import java.util.List; public class DefaultCombinedPreferenceController extends DefaultAppPreferenceController { public class DefaultCombinedPreferenceController extends DefaultAppPreferenceController implements Preference.OnPreferenceClickListener { private static final Intent AUTOFILL_PROBE = new Intent(AutofillService.SERVICE_INTERFACE); private static final String TAG = "DefaultCombinedPreferenceController"; Loading Loading @@ -73,18 +75,55 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon @Override protected Intent getSettingIntent(DefaultAppInfo info) { if (info == null) { return null; // Despite this method being called getSettingIntent this intent actually // opens the primary picker. This is so that we can swap the cog and the left // hand side presses to align the UX. return new Intent(mContext, CredentialsPickerActivity.class); } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); final String prefKey = getPreferenceKey(); final Preference preference = screen.findPreference(prefKey); if (preference != null) { preference.setOnPreferenceClickListener((Preference.OnPreferenceClickListener) this); } final AutofillSettingIntentProvider intentProvider = new AutofillSettingIntentProvider(mContext, getUser(), info.getKey()); return intentProvider.getIntent(); } @Override protected DefaultAppInfo getDefaultAppInfo() { public boolean onPreferenceClick(Preference preference) { // Get the selected provider. final CombinedProviderInfo topProvider = getTopProvider(); if (topProvider == null) { return false; } // If the top provider has a defined Credential Manager settings // provider then we should open that up. final String settingsActivity = topProvider.getSettingsActivity(); if (!TextUtils.isEmpty(settingsActivity)) { final Intent intent = new Intent(Intent.ACTION_MAIN) .setComponent( new ComponentName( topProvider.getPackageName(), settingsActivity)); startActivity(intent); return true; } return false; } private @Nullable CombinedProviderInfo getTopProvider() { List<CombinedProviderInfo> providers = getAllProviders(getUser()); CombinedProviderInfo topProvider = CombinedProviderInfo.getTopProvider(providers); return CombinedProviderInfo.getTopProvider(providers); } @Override protected DefaultAppInfo getDefaultAppInfo() { CombinedProviderInfo topProvider = getTopProvider(); if (topProvider != null) { ServiceInfo brandingService = topProvider.getBrandingService(); if (brandingService == null) { Loading Loading @@ -138,53 +177,6 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon return true; } /** Provides Intent to setting activity for the specified autofill service. */ static final class AutofillSettingIntentProvider { private final String mKey; private final Context mContext; private final int mUserId; public AutofillSettingIntentProvider(Context context, int userId, String key) { mKey = key; mContext = context; mUserId = userId; } public Intent getIntent() { final List<ResolveInfo> resolveInfos = mContext.getPackageManager() .queryIntentServicesAsUser( AUTOFILL_PROBE, PackageManager.GET_META_DATA, mUserId); for (ResolveInfo resolveInfo : resolveInfos) { final ServiceInfo serviceInfo = resolveInfo.serviceInfo; // If there are multiple autofill services then pick the first one. if (mKey != null && mKey.startsWith(serviceInfo.packageName)) { final String settingsActivity; try { settingsActivity = new AutofillServiceInfo(mContext, serviceInfo) .getSettingsActivity(); } catch (SecurityException e) { // Service does not declare the proper permission, ignore it. Log.e(TAG, "Error getting info for " + serviceInfo + ": " + e); return null; } if (TextUtils.isEmpty(settingsActivity)) { return null; } return new Intent(Intent.ACTION_MAIN) .setComponent( new ComponentName(serviceInfo.packageName, settingsActivity)); } } return null; } } protected int getUser() { return UserHandle.myUserId(); } Loading
src/com/android/settings/applications/credentials/DefaultPrivateCombinedPreferenceController.kt +0 −9 Original line number Diff line number Diff line Loading @@ -36,15 +36,6 @@ class DefaultPrivateCombinedPreferenceController(context: Context?) : DefaultCom return "default_credman_autofill_private" } override fun getSettingIntent(info: DefaultAppInfo ?): Intent ? { if (info == null) { return null } return userHandle?.let { handle -> AutofillSettingIntentProvider(mContext, handle.identifier, info.key).intent } ?: null } override fun startActivity(intent: Intent) { userHandle?.let { handle -> mContext.startActivityAsUser(intent, handle) Loading