Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 93e8dff4 authored by Arc Wang's avatar Arc Wang Committed by Android (Google) Code Review
Browse files

Merge "2 panes deep link for large screen devices" into sc-v2-dev

parents 5d3df397 22ce392b
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -107,6 +107,8 @@
    <uses-permission android:name="android.permission.READ_DREAM_STATE" />
    <uses-permission android:name="android.permission.READ_DREAM_SUPPRESSION" />
    <uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION" />
    <uses-permission android:name="android.permission.LAUNCH_TWO_PANE_SETTINGS_DEEP_LINK" />
    <uses-permission android:name="android.permission.ALLOW_PLACE_IN_TWO_PANE_SETTINGS" />

    <application
            android:name=".SettingsApplication"
@@ -172,6 +174,17 @@
            <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/>
        </activity-alias>

        <!-- Alias for SettingsHomepageActivity which works for deep link page in 2-panel. -->
        <activity-alias android:name="DeepLinkHomepageActivity"
                android:label="@string/settings_label_launcher"
                android:exported="true"
                android:targetActivity=".homepage.SettingsHomepageActivity">
            <intent-filter>
                <action android:name="android.settings.SETTINGS_LARGE_SCREEN_DEEP_LINK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity-alias>

        <receiver android:name=".SettingsInitialize"
            android:exported="true">
            <intent-filter>
+23 −0
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@ import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.gateway.SettingsGateway;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
import com.android.settings.homepage.SettingsHomepageActivity;
import com.android.settings.homepage.TopLevelSettings;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wfd.WifiDisplaySettings;
@@ -240,7 +242,22 @@ public class SettingsActivity extends SettingsBaseActivity
        // Should happen before any call to getIntent()
        getMetaData();

        // If it's a deep link intent, start the Activity from SettingsHomepageActivity for 2-pane.
        final Intent intent = getIntent();
        final boolean isFromSettingsHomepage = intent.getBooleanExtra(
                SettingsHomepageActivity.EXTRA_IS_FROM_SETTINGS_HOMEPAGE, /* defaultValue */ false);
        if (ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this) && !isFromSettingsHomepage
                && isOnlyOneActivityInActivityStack()) {
            final Intent trampolineIntent =
                    new Intent(android.provider.Settings.ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK);
            trampolineIntent.putExtra(
                    android.provider.Settings.EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI,
                    intent.toUri(Intent.URI_INTENT_SCHEME));
            startActivity(trampolineIntent);
            finish();
            return;
        }

        if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
            getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
        }
@@ -347,6 +364,12 @@ public class SettingsActivity extends SettingsBaseActivity
        }
    }

    private boolean isOnlyOneActivityInActivityStack() {
        final ActivityManager activityManager = getSystemService(ActivityManager.class);
        List<ActivityManager.RunningTaskInfo> taskList = activityManager.getRunningTasks(2);
        return taskList.get(0).numActivities == 1;
    }

    /** Returns the initial fragment name that the activity will launch. */
    @VisibleForTesting
    public String getInitialFragmentName(Intent intent) {
+26 −24
Original line number Diff line number Diff line
@@ -60,12 +60,34 @@ public class ActivityEmbeddingRulesController {
        mSplitController.clearRegisteredRules();

        // Set a placeholder for home page.
        mSplitController.registerRule(getHomepagePlaceholderRule());
        registerHomepagePlaceholderRule();
        // Set subsettings rule.
        mSplitController.registerRule(getSubSettingsPairRule());
        registerTwoPanePairRule(mContext,
                getComponentName(Settings.class),
                getComponentName(SubSettings.class),
                true /* finishPrimaryWithSecondary */,
                true /* finishSecondaryWithPrimary */);
    }

    private SplitPlaceholderRule getHomepagePlaceholderRule() {
    /** Register a SplitPairRule for 2-pane. */
    public static void registerTwoPanePairRule(Context context,
            ComponentName primary, ComponentName secondary,
            boolean finishPrimaryWithSecondary, boolean finishSecondaryWithPrimary) {
        final Set<SplitPairFilter> filters = new HashSet<>();
        filters.add(new SplitPairFilter(primary, secondary,
                null /* secondaryActivityIntentAction */,
                null /* secondaryActivityIntentCategory */));

        new SplitController(context).registerRule(new SplitPairRule(filters,
                finishPrimaryWithSecondary,
                finishSecondaryWithPrimary, true /* clearTop */,
                ActivityEmbeddingUtils.getMinCurrentScreenSplitWidthPx(context),
                ActivityEmbeddingUtils.getMinSmallestScreenSplitWidthPx(context),
                ActivityEmbeddingUtils.SPLIT_RATIO,
                LayoutDirection.LOCALE));
    }

    private void registerHomepagePlaceholderRule() {
        final Set<ActivityFilter> activityFilters = new HashSet<>();
        activityFilters.add(new ActivityFilter(getComponentName(Settings.class)));
        final Intent intent = new Intent();
@@ -78,27 +100,7 @@ public class ActivityEmbeddingRulesController {
                ActivityEmbeddingUtils.SPLIT_RATIO,
                LayoutDirection.LOCALE);

        return placeholderRule;
    }

    private SplitPairRule getSubSettingsPairRule() {
        final Set<SplitPairFilter> pairFilters = new HashSet<>();
        pairFilters.add(new SplitPairFilter(
                getComponentName(Settings.class),
                getComponentName(SubSettings.class),
                null /* secondaryActivityIntentAction */,
                null /* secondaryActivityIntentCategory */));
        final SplitPairRule rule = new SplitPairRule(
                pairFilters,
                true /* finishPrimaryWithSecondary */,
                true /* finishSecondaryWithPrimary */,
                true /* clearTop */,
                ActivityEmbeddingUtils.getMinCurrentScreenSplitWidthPx(mContext),
                ActivityEmbeddingUtils.getMinSmallestScreenSplitWidthPx(mContext),
                ActivityEmbeddingUtils.SPLIT_RATIO,
                LayoutDirection.LOCALE);

        return rule;
        mSplitController.registerRule(placeholderRule);
    }

    @NonNull
+80 −0
Original line number Diff line number Diff line
@@ -18,8 +18,14 @@ package com.android.settings.homepage;

import android.animation.LayoutTransition;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.View;
@@ -31,21 +37,33 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.window.embedding.SplitController;

import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.accounts.AvatarViewMixin;
import com.android.settings.core.CategoryMixin;
import com.android.settings.core.FeatureFlags;
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;

import java.net.URISyntaxException;

/** Settings homepage activity */
public class SettingsHomepageActivity extends FragmentActivity implements
        CategoryMixin.CategoryHandler {

    private static final String TAG = "SettingsHomepageActivity";

    // Put true value to the intent when startActivity for a deep link intent from this Activity.
    public static final String EXTRA_IS_FROM_SETTINGS_HOMEPAGE = "is_from_settings_homepage";

    // An alias class name of SettingsHomepageActivity.
    private static final String ALIAS_DEEP_LINK = "com.android.settings.DeepLinkHomepageActivity";

    private static final long HOMEPAGE_LOADING_TIMEOUT_MS = 300;

    private View mHomepageView;
@@ -105,6 +123,20 @@ public class SettingsHomepageActivity extends FragmentActivity implements
        showFragment(new TopLevelSettings(), R.id.main_content);
        ((FrameLayout) findViewById(R.id.main_content))
                .getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);

        // Launch the intent from deep link for large screen devices.
        launchDeepLinkIntentToRight();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        // When it's large screen 2-pane and Settings app is in background. Receiving a Intent
        // in this Activity will not finish nor onCreate. setIntent here for this case.
        setIntent(intent);
        // Launch the intent from deep link for large screen devices.
        launchDeepLinkIntentToRight();
    }

    private void showSuggestionFragment() {
@@ -141,6 +173,54 @@ public class SettingsHomepageActivity extends FragmentActivity implements
        fragmentTransaction.commit();
    }

    private void launchDeepLinkIntentToRight() {
        if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this)) {
            return;
        }

        final Intent intent = getIntent();
        if (intent == null || !TextUtils.equals(intent.getAction(),
                Settings.ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK)) {
            return;
        }

        final String intentUriString = intent.getStringExtra(
                Settings.EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI);
        if (TextUtils.isEmpty(intentUriString)) {
            Log.e(TAG, "No EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI to deep link");
            finish();
            return;
        }

        final Intent targetIntent;
        try {
            targetIntent = Intent.parseUri(intentUriString, Intent.URI_INTENT_SCHEME);
        } catch (URISyntaxException e) {
            Log.e(TAG, "Failed to parse deep link intent: " + e);
            finish();
            return;
        }

        final ComponentName targetComponentName = targetIntent.resolveActivity(getPackageManager());
        if (targetComponentName == null) {
            Log.e(TAG, "No valid target for the deep link intent: " + targetIntent);
            finish();
            return;
        }

        targetIntent.setFlags(targetIntent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);

        targetIntent.putExtra(EXTRA_IS_FROM_SETTINGS_HOMEPAGE, true);

        // Set 2-pane pair rule for the external deep link page.
        ActivityEmbeddingRulesController.registerTwoPanePairRule(this,
                new ComponentName(Utils.SETTINGS_PACKAGE_NAME, ALIAS_DEEP_LINK),
                targetComponentName,
                true /* finishPrimaryWithSecondary */,
                true /* finishSecondaryWithPrimary */);
        startActivity(targetIntent);
    }

    private void initHomepageContainer() {
        final View view = findViewById(R.id.homepage_container);
        // Prevent inner RecyclerView gets focus and invokes scrolling.