Loading src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java +24 −8 Original line number Diff line number Diff line Loading @@ -180,15 +180,17 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { } pref.setOnPreferenceClickListener(preference -> { TopLevelHighlightMixin highlightMixin = null; boolean isDuplicateClick = false; if (fragment instanceof TopLevelSettings && ActivityEmbeddingUtils.isEmbeddingActivityEnabled(mContext)) { // Highlight the preference whenever it's clicked final TopLevelSettings topLevelSettings = (TopLevelSettings) fragment; topLevelSettings.setHighlightPreferenceKey(key); highlightMixin = topLevelSettings.getHighlightMixin(); isDuplicateClick = topLevelSettings.isDuplicateClick(preference); } launchIntentOrSelectProfile(activity, tile, intent, sourceMetricsCategory, highlightMixin); highlightMixin, isDuplicateClick); return true; }); } Loading Loading @@ -221,7 +223,7 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { SettingsEnums.DASHBOARD_SUMMARY) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); launchIntentOrSelectProfile(activity, tile, intent, SettingsEnums.DASHBOARD_SUMMARY, /* highlightMixin= */ null); /* highlightMixin= */ null, /* isDuplicateClick= */ false); } private DynamicDataObserver createDynamicDataObserver(String method, Uri uri, Preference pref) { Loading Loading @@ -438,31 +440,45 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { } private void launchIntentOrSelectProfile(FragmentActivity activity, Tile tile, Intent intent, int sourceMetricCategory, TopLevelHighlightMixin highlightMixin) { int sourceMetricCategory, TopLevelHighlightMixin highlightMixin, boolean isDuplicateClick) { if (!isIntentResolvable(intent)) { Log.w(TAG, "Cannot resolve intent, skipping. " + intent); return; } ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile); mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); if (tile.userHandle == null || tile.isPrimaryProfileOnly()) { if (!isDuplicateClick) { mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); activity.startActivity(intent); } } else if (tile.userHandle.size() == 1) { if (!isDuplicateClick) { mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); activity.startActivityAsUser(intent, tile.userHandle.get(0)); } } else { final UserHandle userHandle = intent.getParcelableExtra(EXTRA_USER); if (userHandle != null && tile.userHandle.contains(userHandle)) { if (!isDuplicateClick) { mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); activity.startActivityAsUser(intent, userHandle); } return; } final List<UserHandle> resolvableUsers = getResolvableUsers(intent, tile); if (resolvableUsers.size() == 1) { if (!isDuplicateClick) { mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); activity.startActivityAsUser(intent, resolvableUsers.get(0)); } return; } // Show the profile select dialog regardless of the duplicate click. mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); ProfileSelectDialog.show(activity.getSupportFragmentManager(), tile, sourceMetricCategory, /* onShowListener= */ highlightMixin, /* onDismissListener= */ highlightMixin, Loading src/com/android/settings/homepage/TopLevelHighlightMixin.java +4 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,10 @@ public class TopLevelHighlightMixin implements Parcelable, DialogInterface.OnSho } } String getHighlightPreferenceKey() { return mCurrentKey; } void highlightPreferenceIfNeeded() { if (mTopLevelAdapter != null) { mTopLevelAdapter.requestHighlight(); Loading src/com/android/settings/homepage/TopLevelSettings.java +72 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,17 @@ package com.android.settings.homepage; import static android.provider.Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI; import static com.android.settings.search.actionbar.SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR; import static com.android.settingslib.search.SearchIndexable.MOBILE; import android.app.ActivityManager; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.Bundle; Loading @@ -38,6 +43,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.window.embedding.SplitController; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; import com.android.settings.activityembedding.ActivityEmbeddingRulesController; import com.android.settings.activityembedding.ActivityEmbeddingUtils; Loading @@ -51,12 +57,15 @@ import com.android.settingslib.core.instrumentation.Instrumentable; import com.android.settingslib.drawer.Tile; import com.android.settingslib.search.SearchIndexable; import java.net.URISyntaxException; @SearchIndexable(forTarget = MOBILE) public class TopLevelSettings extends DashboardFragment implements SplitLayoutListener, PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { private static final String TAG = "TopLevelSettings"; private static final String SAVED_HIGHLIGHT_MIXIN = "highlight_mixin"; private static final String SAVED_FIRST_PREFERENCE_CLICK = "first_pref_click"; private static final String PREF_KEY_SUPPORT = "top_level_support"; private boolean mIsEmbeddingActivityEnabled; Loading @@ -64,6 +73,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi private int mPaddingHorizontal; private boolean mScrollNeeded = true; private boolean mFirstStarted = true; private boolean mFirstDuplicateClickCheck = true; public TopLevelSettings() { final Bundle args = new Bundle(); Loading Loading @@ -107,6 +117,10 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi @Override public boolean onPreferenceTreeClick(Preference preference) { if (isDuplicateClick(preference)) { return true; } // Register SplitPairRule for SubSettings. ActivityEmbeddingRulesController.registerSubSettingsPairRule(getContext(), true /* clearTop */); Loading Loading @@ -140,6 +154,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi boolean activityEmbedded = SplitController.getInstance().isActivityEmbedded(getActivity()); if (icicle != null) { mFirstDuplicateClickCheck = icicle.getBoolean(SAVED_FIRST_PREFERENCE_CLICK); mHighlightMixin = icicle.getParcelable(SAVED_HIGHLIGHT_MIXIN); mScrollNeeded = !mHighlightMixin.isActivityEmbedded() && activityEmbedded; mHighlightMixin.setActivityEmbedded(activityEmbedded); Loading Loading @@ -173,6 +188,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(SAVED_FIRST_PREFERENCE_CLICK, mFirstDuplicateClickCheck); if (mHighlightMixin != null) { outState.putParcelable(SAVED_HIGHLIGHT_MIXIN, mHighlightMixin); } Loading Loading @@ -271,6 +287,41 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi } } /** Returns whether clicking the specified preference is considered as a duplicate click. */ public boolean isDuplicateClick(Preference pref) { boolean firstCheck = mFirstDuplicateClickCheck; mFirstDuplicateClickCheck = false; /* * Return false when * 1. The device doesn't support activity embedding * 2. The target preference is not highlighted * 3. The current activity is not embedded */ if (mHighlightMixin == null || !TextUtils.equals(pref.getKey(), mHighlightMixin.getHighlightPreferenceKey()) || !SplitController.getInstance().isActivityEmbedded(getActivity())) { return false; } /* * Return true when * 1. This method has been called before * 2. The preference doesn't have a target fragment, ex. Wallpaper and injections */ if (!firstCheck || TextUtils.isEmpty(pref.getFragment())) { return true; } /* * Returns true when * 1. The right pane fragment is not started by a deep link. * 2. The target fragment equals the right pane fragment */ String intentUri = getIntent().getStringExtra(EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI); return TextUtils.isEmpty(intentUri) || TextUtils.equals(pref.getFragment(), getIntentTargetFragment(intentUri)); } /** Show/hide the highlight on the menu entry for the search page presence */ public void setMenuHighlightShowed(boolean show) { if (mHighlightMixin != null) { Loading Loading @@ -310,6 +361,27 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi } } private String getIntentTargetFragment(String intentUri) { Intent targetIntent; try { targetIntent = Intent.parseUri(intentUri, Intent.URI_INTENT_SCHEME); } catch (URISyntaxException e) { return null; } String fragment = targetIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT); if (!TextUtils.isEmpty(fragment)) { return fragment; } ActivityInfo info = targetIntent.resolveActivityInfo(getPackageManager(), PackageManager.GET_META_DATA); if (info == null || info.metaData == null) { return null; } return info.metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS); } private void iteratePreferences(PreferenceJob job) { if (job == null || getPreferenceManager() == null) { return; Loading Loading
src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java +24 −8 Original line number Diff line number Diff line Loading @@ -180,15 +180,17 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { } pref.setOnPreferenceClickListener(preference -> { TopLevelHighlightMixin highlightMixin = null; boolean isDuplicateClick = false; if (fragment instanceof TopLevelSettings && ActivityEmbeddingUtils.isEmbeddingActivityEnabled(mContext)) { // Highlight the preference whenever it's clicked final TopLevelSettings topLevelSettings = (TopLevelSettings) fragment; topLevelSettings.setHighlightPreferenceKey(key); highlightMixin = topLevelSettings.getHighlightMixin(); isDuplicateClick = topLevelSettings.isDuplicateClick(preference); } launchIntentOrSelectProfile(activity, tile, intent, sourceMetricsCategory, highlightMixin); highlightMixin, isDuplicateClick); return true; }); } Loading Loading @@ -221,7 +223,7 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { SettingsEnums.DASHBOARD_SUMMARY) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); launchIntentOrSelectProfile(activity, tile, intent, SettingsEnums.DASHBOARD_SUMMARY, /* highlightMixin= */ null); /* highlightMixin= */ null, /* isDuplicateClick= */ false); } private DynamicDataObserver createDynamicDataObserver(String method, Uri uri, Preference pref) { Loading Loading @@ -438,31 +440,45 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { } private void launchIntentOrSelectProfile(FragmentActivity activity, Tile tile, Intent intent, int sourceMetricCategory, TopLevelHighlightMixin highlightMixin) { int sourceMetricCategory, TopLevelHighlightMixin highlightMixin, boolean isDuplicateClick) { if (!isIntentResolvable(intent)) { Log.w(TAG, "Cannot resolve intent, skipping. " + intent); return; } ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile); mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); if (tile.userHandle == null || tile.isPrimaryProfileOnly()) { if (!isDuplicateClick) { mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); activity.startActivity(intent); } } else if (tile.userHandle.size() == 1) { if (!isDuplicateClick) { mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); activity.startActivityAsUser(intent, tile.userHandle.get(0)); } } else { final UserHandle userHandle = intent.getParcelableExtra(EXTRA_USER); if (userHandle != null && tile.userHandle.contains(userHandle)) { if (!isDuplicateClick) { mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); activity.startActivityAsUser(intent, userHandle); } return; } final List<UserHandle> resolvableUsers = getResolvableUsers(intent, tile); if (resolvableUsers.size() == 1) { if (!isDuplicateClick) { mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); activity.startActivityAsUser(intent, resolvableUsers.get(0)); } return; } // Show the profile select dialog regardless of the duplicate click. mMetricsFeatureProvider.logStartedIntent(intent, sourceMetricCategory); ProfileSelectDialog.show(activity.getSupportFragmentManager(), tile, sourceMetricCategory, /* onShowListener= */ highlightMixin, /* onDismissListener= */ highlightMixin, Loading
src/com/android/settings/homepage/TopLevelHighlightMixin.java +4 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,10 @@ public class TopLevelHighlightMixin implements Parcelable, DialogInterface.OnSho } } String getHighlightPreferenceKey() { return mCurrentKey; } void highlightPreferenceIfNeeded() { if (mTopLevelAdapter != null) { mTopLevelAdapter.requestHighlight(); Loading
src/com/android/settings/homepage/TopLevelSettings.java +72 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,17 @@ package com.android.settings.homepage; import static android.provider.Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI; import static com.android.settings.search.actionbar.SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR; import static com.android.settingslib.search.SearchIndexable.MOBILE; import android.app.ActivityManager; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.Bundle; Loading @@ -38,6 +43,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.window.embedding.SplitController; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.Utils; import com.android.settings.activityembedding.ActivityEmbeddingRulesController; import com.android.settings.activityembedding.ActivityEmbeddingUtils; Loading @@ -51,12 +57,15 @@ import com.android.settingslib.core.instrumentation.Instrumentable; import com.android.settingslib.drawer.Tile; import com.android.settingslib.search.SearchIndexable; import java.net.URISyntaxException; @SearchIndexable(forTarget = MOBILE) public class TopLevelSettings extends DashboardFragment implements SplitLayoutListener, PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { private static final String TAG = "TopLevelSettings"; private static final String SAVED_HIGHLIGHT_MIXIN = "highlight_mixin"; private static final String SAVED_FIRST_PREFERENCE_CLICK = "first_pref_click"; private static final String PREF_KEY_SUPPORT = "top_level_support"; private boolean mIsEmbeddingActivityEnabled; Loading @@ -64,6 +73,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi private int mPaddingHorizontal; private boolean mScrollNeeded = true; private boolean mFirstStarted = true; private boolean mFirstDuplicateClickCheck = true; public TopLevelSettings() { final Bundle args = new Bundle(); Loading Loading @@ -107,6 +117,10 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi @Override public boolean onPreferenceTreeClick(Preference preference) { if (isDuplicateClick(preference)) { return true; } // Register SplitPairRule for SubSettings. ActivityEmbeddingRulesController.registerSubSettingsPairRule(getContext(), true /* clearTop */); Loading Loading @@ -140,6 +154,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi boolean activityEmbedded = SplitController.getInstance().isActivityEmbedded(getActivity()); if (icicle != null) { mFirstDuplicateClickCheck = icicle.getBoolean(SAVED_FIRST_PREFERENCE_CLICK); mHighlightMixin = icicle.getParcelable(SAVED_HIGHLIGHT_MIXIN); mScrollNeeded = !mHighlightMixin.isActivityEmbedded() && activityEmbedded; mHighlightMixin.setActivityEmbedded(activityEmbedded); Loading Loading @@ -173,6 +188,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(SAVED_FIRST_PREFERENCE_CLICK, mFirstDuplicateClickCheck); if (mHighlightMixin != null) { outState.putParcelable(SAVED_HIGHLIGHT_MIXIN, mHighlightMixin); } Loading Loading @@ -271,6 +287,41 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi } } /** Returns whether clicking the specified preference is considered as a duplicate click. */ public boolean isDuplicateClick(Preference pref) { boolean firstCheck = mFirstDuplicateClickCheck; mFirstDuplicateClickCheck = false; /* * Return false when * 1. The device doesn't support activity embedding * 2. The target preference is not highlighted * 3. The current activity is not embedded */ if (mHighlightMixin == null || !TextUtils.equals(pref.getKey(), mHighlightMixin.getHighlightPreferenceKey()) || !SplitController.getInstance().isActivityEmbedded(getActivity())) { return false; } /* * Return true when * 1. This method has been called before * 2. The preference doesn't have a target fragment, ex. Wallpaper and injections */ if (!firstCheck || TextUtils.isEmpty(pref.getFragment())) { return true; } /* * Returns true when * 1. The right pane fragment is not started by a deep link. * 2. The target fragment equals the right pane fragment */ String intentUri = getIntent().getStringExtra(EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI); return TextUtils.isEmpty(intentUri) || TextUtils.equals(pref.getFragment(), getIntentTargetFragment(intentUri)); } /** Show/hide the highlight on the menu entry for the search page presence */ public void setMenuHighlightShowed(boolean show) { if (mHighlightMixin != null) { Loading Loading @@ -310,6 +361,27 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi } } private String getIntentTargetFragment(String intentUri) { Intent targetIntent; try { targetIntent = Intent.parseUri(intentUri, Intent.URI_INTENT_SCHEME); } catch (URISyntaxException e) { return null; } String fragment = targetIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT); if (!TextUtils.isEmpty(fragment)) { return fragment; } ActivityInfo info = targetIntent.resolveActivityInfo(getPackageManager(), PackageManager.GET_META_DATA); if (info == null || info.metaData == null) { return null; } return info.metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS); } private void iteratePreferences(PreferenceJob job) { if (job == null || getPreferenceManager() == null) { return; Loading