1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.activityembedding;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.os.SystemProperties;
22 import android.util.DisplayMetrics;
23 import android.util.FeatureFlagUtils;
24 import android.util.Log;
25 import android.util.TypedValue;
26 
27 import androidx.window.embedding.ActivityEmbeddingController;
28 import androidx.window.embedding.SplitController;
29 
30 import com.android.settings.R;
31 
32 import com.google.android.setupcompat.util.WizardManagerHelper;
33 
34 /** An util class collecting all common methods for the embedding activity features. */
35 public class ActivityEmbeddingUtils {
36     // The minimum width of the activity to show the regular homepage layout.
37     private static final float MIN_REGULAR_HOMEPAGE_LAYOUT_WIDTH_DP = 380f;
38 
39     /**
40      * Indicates whether to enable large screen optimization if the device supports
41      * the Activity Embedding split feature.
42      * <p>
43      * Note that the large screen optimization won't be enabled if the device doesn't support the
44      * Activity Embedding feature regardless of this property value.
45      *
46      * @see androidx.window.embedding.SplitController#getSplitSupportStatus
47      * @see androidx.window.embedding.SplitController.SplitSupportStatus#SPLIT_AVAILABLE
48      * @see androidx.window.embedding.SplitController.SplitSupportStatus#SPLIT_UNAVAILABLE
49      */
50     private static final boolean SHOULD_ENABLE_LARGE_SCREEN_OPTIMIZATION =
51             SystemProperties.getBoolean("persist.settings.large_screen_opt.enabled", false);
52 
53     private static final String TAG = "ActivityEmbeddingUtils";
54 
55     /** Get the smallest width dp of the window when the split should be used. */
getMinCurrentScreenSplitWidthDp(Context context)56     public static int getMinCurrentScreenSplitWidthDp(Context context) {
57         return context.getResources().getInteger(R.integer.config_activity_embed_split_min_cur_dp);
58     }
59 
60     /**
61      * Get the smallest dp value of the smallest-width (sw) of the window in any rotation when
62      * the split should be used.
63      */
getMinSmallestScreenSplitWidthDp(Context context)64     public static int getMinSmallestScreenSplitWidthDp(Context context) {
65         return context.getResources().getInteger(R.integer.config_activity_embed_split_min_sw_dp);
66     }
67 
68     /**
69      * Get the ratio to use when splitting windows. This should be a float which describes
70      * the percentage of the screen which the first window should occupy.
71      */
getSplitRatio(Context context)72     public static float getSplitRatio(Context context) {
73         return context.getResources().getFloat(R.dimen.config_activity_embed_split_ratio);
74     }
75 
76     /**
77      * Returns {@code true} to indicate that Settings app support the Activity Embedding feature on
78      * this device. Returns {@code false}, otherwise.
79      */
isSettingsSplitEnabled(Context context)80     public static boolean isSettingsSplitEnabled(Context context) {
81         return SHOULD_ENABLE_LARGE_SCREEN_OPTIMIZATION
82                 && SplitController.getInstance(context).getSplitSupportStatus()
83                 == SplitController.SplitSupportStatus.SPLIT_AVAILABLE;
84     }
85 
86     /**
87      * Checks whether to support embedding activity feature with following conditions:
88      * <ul>
89      *     <li>Whether {@link #isSettingsSplitEnabled(Context)}</li>
90      *     <li>Whether {@link FeatureFlagUtils#SETTINGS_SUPPORT_LARGE_SCREEN} is enabled</li>
91      *     <li>Whether User setup is completed</li>
92      * </ul>
93      */
isEmbeddingActivityEnabled(Context context)94     public static boolean isEmbeddingActivityEnabled(Context context) {
95         // Activity Embedding feature is not enabled if Settings doesn't enable large screen
96         // optimization or the device is not supported.
97         if (!isSettingsSplitEnabled(context)) {
98             Log.d(TAG, "isSettingsSplitSupported = false");
99             return false;
100         }
101         // Activity Embedding feature is not enabled if a user chooses to disable the feature.
102         if (!FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_SUPPORT_LARGE_SCREEN)) {
103             Log.d(TAG, "isFlagEnabled = false");
104             return false;
105         }
106         // Don't enable Activity embedding for setup wizard.
107         if (!WizardManagerHelper.isUserSetupComplete(context)) {
108             Log.d(TAG, "isUserSetupComplete = false");
109             return false;
110         }
111         Log.d(TAG, "isEmbeddingActivityEnabled = true");
112         return true;
113     }
114 
115     /** Whether to show the regular or simplified homepage layout. */
isRegularHomepageLayout(Activity activity)116     public static boolean isRegularHomepageLayout(Activity activity) {
117         DisplayMetrics dm = activity.getResources().getDisplayMetrics();
118         return dm.widthPixels >= (int) TypedValue.applyDimension(
119                 TypedValue.COMPLEX_UNIT_DIP, MIN_REGULAR_HOMEPAGE_LAYOUT_WIDTH_DP, dm);
120     }
121 
122     /**
123      * Check if activity is already embedded
124      */
isAlreadyEmbedded(Activity activity)125     public static boolean isAlreadyEmbedded(Activity activity) {
126         return isEmbeddingActivityEnabled(activity) && ActivityEmbeddingController.getInstance(
127                 activity).isActivityEmbedded(activity);
128     }
129 }
130