blob: 4e39070febd16efc4604e291b42d4c36470199e5 [file] [log] [blame]
/*
* Copyright (C) 2021 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.activityembedding;
import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.FeatureFlagUtils;
import android.util.Log;
import androidx.window.embedding.ActivityFilter;
import androidx.window.embedding.ActivityRule;
import androidx.window.embedding.EmbeddingAspectRatio;
import androidx.window.embedding.RuleController;
import androidx.window.embedding.SplitAttributes;
import androidx.window.embedding.SplitPairFilter;
import androidx.window.embedding.SplitPairRule;
import androidx.window.embedding.SplitPlaceholderRule;
import androidx.window.embedding.SplitRule;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.biometrics.face.FaceEnrollIntroduction;
import com.android.settings.biometrics.face.FaceEnrollIntroductionInternal;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroductionInternal;
import com.android.settings.biometrics2.ui.view.FingerprintEnrollmentActivity;
import com.android.settings.core.FeatureFlags;
import com.android.settings.homepage.DeepLinkHomepageActivity;
import com.android.settings.homepage.DeepLinkHomepageActivityInternal;
import com.android.settings.homepage.SettingsHomepageActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockPattern;
import com.android.settings.remoteauth.RemoteAuthActivity;
import com.android.settings.remoteauth.RemoteAuthActivityInternal;
import com.android.settingslib.users.AvatarPickerActivity;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/** A class to initialize split rules for activity embedding. */
public class ActivityEmbeddingRulesController {
private static final String TAG = "ActivityEmbeddingCtrl";
private static final ComponentName COMPONENT_NAME_WILDCARD = new ComponentName(
"*" /* pkg */, "*" /* cls */);
private final Context mContext;
private final RuleController mRuleController;
public ActivityEmbeddingRulesController(Context context) {
mContext = context;
mRuleController = RuleController.getInstance(context);
}
/**
* Set up embedding rules to place activities to the right pane.
*/
public void initRules() {
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(mContext)) {
Log.d(TAG, "Not support this feature now");
return;
}
mRuleController.clearRules();
// Set a placeholder for home page.
registerHomepagePlaceholderRule();
registerAlwaysExpandRule();
}
/** Register a SplitPairRule for 2-pane. */
public static void registerTwoPanePairRule(Context context,
ComponentName primaryComponent,
ComponentName secondaryComponent,
String secondaryIntentAction,
SplitRule.FinishBehavior finishPrimaryWithSecondary,
SplitRule.FinishBehavior finishSecondaryWithPrimary,
boolean clearTop) {
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(context)) {
return;
}
final Set<SplitPairFilter> filters = new HashSet<>();
filters.add(new SplitPairFilter(primaryComponent, secondaryComponent,
secondaryIntentAction));
SplitAttributes attributes = new SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(
ActivityEmbeddingUtils.getSplitRatio(context)))
.setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
.build();
SplitPairRule splitPairRule = new SplitPairRule.Builder(filters)
.setFinishPrimaryWithSecondary(finishPrimaryWithSecondary)
.setFinishSecondaryWithPrimary(finishSecondaryWithPrimary)
.setClearTop(clearTop)
.setMinWidthDp(ActivityEmbeddingUtils.getMinCurrentScreenSplitWidthDp(context))
.setMinSmallestWidthDp(
ActivityEmbeddingUtils.getMinSmallestScreenSplitWidthDp(context))
.setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
.setDefaultSplitAttributes(attributes)
.build();
RuleController.getInstance(context).addRule(splitPairRule);
}
/**
* Registers a {@link SplitPairRule} for all classes that Settings homepage can be invoked from.
*/
public static void registerTwoPanePairRuleForSettingsHome(Context context,
ComponentName secondaryComponent,
String secondaryIntentAction,
boolean finishPrimaryWithSecondary,
boolean finishSecondaryWithPrimary,
boolean clearTop) {
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(context)) {
return;
}
registerTwoPanePairRule(
context,
new ComponentName(context, Settings.class),
secondaryComponent,
secondaryIntentAction,
finishPrimaryWithSecondary ? SplitRule.FinishBehavior.ADJACENT
: SplitRule.FinishBehavior.NEVER,
finishSecondaryWithPrimary ? SplitRule.FinishBehavior.ADJACENT
: SplitRule.FinishBehavior.NEVER,
clearTop);
registerTwoPanePairRule(
context,
new ComponentName(context, SettingsHomepageActivity.class),
secondaryComponent,
secondaryIntentAction,
finishPrimaryWithSecondary ? SplitRule.FinishBehavior.ADJACENT
: SplitRule.FinishBehavior.NEVER,
finishSecondaryWithPrimary ? SplitRule.FinishBehavior.ADJACENT
: SplitRule.FinishBehavior.NEVER,
clearTop);
// We should finish HomePageActivity altogether even if it shows in single pane for all deep
// link cases.
registerTwoPanePairRule(
context,
new ComponentName(context, DeepLinkHomepageActivity.class),
secondaryComponent,
secondaryIntentAction,
finishPrimaryWithSecondary ? SplitRule.FinishBehavior.ALWAYS
: SplitRule.FinishBehavior.NEVER,
finishSecondaryWithPrimary ? SplitRule.FinishBehavior.ALWAYS
: SplitRule.FinishBehavior.NEVER,
clearTop);
registerTwoPanePairRule(
context,
new ComponentName(context, DeepLinkHomepageActivityInternal.class),
secondaryComponent,
secondaryIntentAction,
finishPrimaryWithSecondary ? SplitRule.FinishBehavior.ALWAYS
: SplitRule.FinishBehavior.NEVER,
finishSecondaryWithPrimary ? SplitRule.FinishBehavior.ALWAYS
: SplitRule.FinishBehavior.NEVER,
clearTop);
}
/**
* Register a new SplitPairRule for Settings home.
*/
public static void registerTwoPanePairRuleForSettingsHome(Context context,
ComponentName secondaryComponent,
String secondaryIntentAction,
boolean clearTop) {
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(context)) {
return;
}
registerTwoPanePairRuleForSettingsHome(
context,
secondaryComponent,
secondaryIntentAction,
true /* finishPrimaryWithSecondary */,
true /* finishSecondaryWithPrimary */,
clearTop);
}
/** Register a SplitPairRule for SubSettings if the device supports 2-pane. */
public static void registerSubSettingsPairRule(Context context, boolean clearTop) {
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(context)) {
return;
}
registerTwoPanePairRuleForSettingsHome(
context,
new ComponentName(context, SubSettings.class),
null /* secondaryIntentAction */,
clearTop);
registerTwoPanePairRuleForSettingsHome(
context,
COMPONENT_NAME_WILDCARD,
Intent.ACTION_SAFETY_CENTER,
clearTop
);
}
private void registerHomepagePlaceholderRule() {
final Set<ActivityFilter> activityFilters = new HashSet<>();
addActivityFilter(activityFilters, SettingsHomepageActivity.class);
addActivityFilter(activityFilters, Settings.class);
final Intent intent = new Intent(mContext, Settings.NetworkDashboardActivity.class);
intent.putExtra(SettingsActivity.EXTRA_IS_SECOND_LAYER_PAGE, true);
SplitAttributes attributes = new SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(
ActivityEmbeddingUtils.getSplitRatio(mContext)))
.build();
final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule.Builder(
activityFilters, intent)
.setMinWidthDp(ActivityEmbeddingUtils.getMinCurrentScreenSplitWidthDp(mContext))
.setMinSmallestWidthDp(
ActivityEmbeddingUtils.getMinSmallestScreenSplitWidthDp(mContext))
.setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ALWAYS_ALLOW)
.setSticky(false)
.setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ADJACENT)
.setDefaultSplitAttributes(attributes)
.build();
mRuleController.addRule(placeholderRule);
}
private void registerAlwaysExpandRule() {
final Set<ActivityFilter> activityFilters = new HashSet<>();
if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.SETTINGS_SEARCH_ALWAYS_EXPAND)) {
final Intent searchIntent = FeatureFactory.getFeatureFactory()
.getSearchFeatureProvider()
.buildSearchIntent(mContext, SettingsEnums.SETTINGS_HOMEPAGE);
addActivityFilter(activityFilters, searchIntent);
}
addActivityFilter(activityFilters, FingerprintEnrollmentActivity.class);
addActivityFilter(activityFilters, FingerprintEnrollmentActivity.InternalActivity.class);
addActivityFilter(activityFilters, FingerprintEnrollIntroduction.class);
addActivityFilter(activityFilters, FingerprintEnrollIntroductionInternal.class);
addActivityFilter(activityFilters, FingerprintEnrollEnrolling.class);
addActivityFilter(activityFilters, FaceEnrollIntroductionInternal.class);
addActivityFilter(activityFilters, FaceEnrollIntroduction.class);
addActivityFilter(activityFilters, RemoteAuthActivity.class);
addActivityFilter(activityFilters, RemoteAuthActivityInternal.class);
addActivityFilter(activityFilters, ChooseLockPattern.class);
if (android.multiuser.Flags.avatarSync()) {
String action = mContext.getString(R.string.config_avatar_picker_action);
addActivityFilter(activityFilters, new Intent(action));
} else {
addActivityFilter(activityFilters, AvatarPickerActivity.class);
}
ActivityRule activityRule = new ActivityRule.Builder(activityFilters).setAlwaysExpand(true)
.build();
mRuleController.addRule(activityRule);
}
private static void addActivityFilter(Set<ActivityFilter> activityFilters, Intent intent) {
activityFilters.add(new ActivityFilter(COMPONENT_NAME_WILDCARD, intent.getAction()));
}
private void addActivityFilter(Collection<ActivityFilter> activityFilters,
Class<? extends Activity> activityClass) {
activityFilters.add(new ActivityFilter(new ComponentName(mContext, activityClass),
null /* intentAction */));
}
}