diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 64bef730cb8..222931e286d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -108,7 +108,9 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4041,7 +4589,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -4057,7 +4605,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -4073,7 +4621,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -4089,7 +4637,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -4105,7 +4653,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -4137,7 +4685,7 @@ errorLine2=" ^"> @@ -4153,7 +4701,7 @@ errorLine2=" ^"> @@ -4169,7 +4717,7 @@ errorLine2=" ^"> @@ -4185,7 +4733,7 @@ errorLine2=" ^"> @@ -4201,7 +4749,7 @@ errorLine2=" ^"> @@ -4217,7 +4765,7 @@ errorLine2=" ^"> @@ -4233,7 +4781,7 @@ errorLine2=" ^"> @@ -4249,7 +4797,7 @@ errorLine2=" ^"> @@ -4265,7 +4813,7 @@ errorLine2=" ^"> @@ -4281,7 +4829,7 @@ errorLine2=" ^"> @@ -4297,7 +4845,7 @@ errorLine2=" ^"> @@ -4313,7 +4861,7 @@ errorLine2=" ^"> @@ -4329,7 +4877,7 @@ errorLine2=" ^"> @@ -4493,259 +5041,4 @@ column="5"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com/android/settings/SettingsApplication.java b/src/com/android/settings/SettingsApplication.java new file mode 100644 index 00000000000..7aa5af8b84c --- /dev/null +++ b/src/com/android/settings/SettingsApplication.java @@ -0,0 +1,34 @@ +/* + * 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; + +import android.app.Application; + +import com.android.settings.activityembedding.ActivityEmbeddingRulesController; + +/** Settings application which sets up activity embedding rules for the large screen device. */ +public class SettingsApplication extends Application { + + @Override + public void onCreate() { + super.onCreate(); + + final ActivityEmbeddingRulesController controller = + new ActivityEmbeddingRulesController(this); + controller.initRules(); + } +} diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java new file mode 100644 index 00000000000..f1a1ecd023b --- /dev/null +++ b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java @@ -0,0 +1,108 @@ +/* + * 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.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.util.LayoutDirection; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.window.embedding.ActivityFilter; +import androidx.window.embedding.SplitController; +import androidx.window.embedding.SplitPairFilter; +import androidx.window.embedding.SplitPairRule; +import androidx.window.embedding.SplitPlaceholderRule; + +import com.android.settings.Settings; +import com.android.settings.SubSettings; + +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 final Context mContext; + private final SplitController mSplitController; + + public ActivityEmbeddingRulesController(Context context) { + mContext = context; + mSplitController = new SplitController(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; + } + + mSplitController.clearRegisteredRules(); + + // Set a placeholder for home page. + mSplitController.registerRule(getHomepagePlaceholderRule()); + // Set subsettings rule. + mSplitController.registerRule(getSubSettingsPairRule()); + } + + private SplitPlaceholderRule getHomepagePlaceholderRule() { + final Set activityFilters = new HashSet<>(); + activityFilters.add(new ActivityFilter(getComponentName(Settings.class))); + final Intent intent = new Intent(); + intent.setComponent(getComponentName(Settings.NetworkDashboardActivity.class)); + final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule( + activityFilters, + intent, + ActivityEmbeddingUtils.getMinCurrentScreenSplitWidthPx(mContext), + ActivityEmbeddingUtils.getMinSmallestScreenSplitWidthPx(mContext), + ActivityEmbeddingUtils.SPLIT_RATIO, + LayoutDirection.LOCALE); + + return placeholderRule; + } + + private SplitPairRule getSubSettingsPairRule() { + final Set 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; + } + + @NonNull + private ComponentName getComponentName(Class activityClass) { + return new ComponentName(mContext.getPackageName(), activityClass.getName()); + } +} diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java b/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java new file mode 100644 index 00000000000..96c37773fc1 --- /dev/null +++ b/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java @@ -0,0 +1,65 @@ +/* + * 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.content.Context; +import android.util.DisplayMetrics; +import android.util.FeatureFlagUtils; +import android.util.Log; +import android.util.TypedValue; + +import androidx.window.embedding.SplitController; + +/** An util class collecting all common methods for the embedding activity features. */ +public class ActivityEmbeddingUtils { + public static final float SPLIT_RATIO = 0.5f; + // The smallest value of current width of the window when the split should be used. + private static final float MIN_CURRENT_SCREEN_SPLIT_WIDTH_DP = 600f; + // The smallest value of the smallest-width (sw) of the window in any rotation when + // the split should be used. + private static final float MIN_SMALLEST_SCREEN_SPLIT_WIDTH_DP = 600f; + private static final String TAG = "ActivityEmbeddingUtils"; + + /** Get the smallest pixel value of width of the window when the split should be used. */ + public static int getMinCurrentScreenSplitWidthPx(Context context) { + final DisplayMetrics dm = context.getResources().getDisplayMetrics(); + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, MIN_CURRENT_SCREEN_SPLIT_WIDTH_DP, dm); + } + + /** + * Get the smallest pixel value of the smallest-width (sw) of the window in any rotation when + * the split should be used. + */ + public static int getMinSmallestScreenSplitWidthPx(Context context) { + final DisplayMetrics dm = context.getResources().getDisplayMetrics(); + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, MIN_SMALLEST_SCREEN_SPLIT_WIDTH_DP, dm); + } + + /** Whether to support embedding activity feature. */ + public static boolean isEmbeddingActivityEnabled(Context context) { + final boolean isFlagEnabled = FeatureFlagUtils.isEnabled(context, + FeatureFlagUtils.SETTINGS_SUPPORT_LARGE_SCREEN); + final boolean isSplitSupported = new SplitController(context).isSplitSupported(); + + Log.d(TAG, "isFlagEnabled = " + isFlagEnabled); + Log.d(TAG, "isSplitSupported = " + isSplitSupported); + + return isFlagEnabled && isSplitSupported; + } +}