diff --git a/AndroidManifest.xml b/AndroidManifest.xml index c88639f39f1..d8bbe8f2de7 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -108,7 +108,9 @@ - + + + + + errorLine1=" <color name="SIM_color_cyan">#ff006D74</color> <!-- Material Custom Cyan -->" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" <color name="SIM_color_blue800">#ff185ABC</color> <!-- Material Blue 800 -->" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" <color name="SIM_color_green800">#ff137333</color> <!-- Material Green 800 -->" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" <color name="SIM_color_purple800">#ff7627bb</color> <!-- Material Purple 800 -->" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" <color name="SIM_color_pink800">#ffb80672</color> <!-- Material Pink 800 -->" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" <color name="SIM_color_orange">#ff995400</color> <!-- Material Custom Orange -->" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + + + + + + + + + + + + + + + + + + + + + @@ -1997,7 +2105,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2013,7 +2121,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2029,7 +2137,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2045,7 +2153,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2061,7 +2169,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2077,7 +2185,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -4653,7 +4761,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> diff --git a/libs/window_ext_lib.aar b/libs/window_ext_lib.aar index b1a95113d2d..cb1f242672e 100644 Binary files a/libs/window_ext_lib.aar and b/libs/window_ext_lib.aar differ diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 4a8d9333680..1ecddf5a79f 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -1179,14 +1179,24 @@ Cached (empty) + + + @color/SIM_color_cyan + @color/SIM_color_blue800 + @color/SIM_color_green800 + @color/SIM_color_purple800 + @color/SIM_color_pink800 + @color/SIM_color_orange + + - Teal + Cyan Blue - Indigo + Green Purple Pink - Red + Orange #ffd32f2f + + #ff006D74 + #ff185ABC + #ff137333 + #ff7627bb + #ffb80672 + #ff995400 + - #ff80cbc4 - #ff90caf9 - #ffc5cae9 - #ffe1bee7 - #fff48fb1 - #ffef9a9a + #ff4DD0E1 + #ff8AB4F8 + #ff81C995 + #ffC58AF9 + #ffff8bcb + #fffcad70 @*android:color/surface_header_light diff --git a/res/values/strings.xml b/res/values/strings.xml index 38df458f37b..e6a9ceb4801 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5192,7 +5192,7 @@ Create widget and allow access? - After you create the widget, %1$s can access all data it displays. + After you create the widget, the application can access everything displayed.\n\nApplication: %1$s\nWidget: %2$s\n Always allow %1$s to create widgets and access their data diff --git a/src/com/android/settings/AllowBindAppWidgetActivity.java b/src/com/android/settings/AllowBindAppWidgetActivity.java index e7f7a6af203..0272c83702e 100644 --- a/src/com/android/settings/AllowBindAppWidgetActivity.java +++ b/src/com/android/settings/AllowBindAppWidgetActivity.java @@ -19,6 +19,7 @@ package com.android.settings; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; @@ -122,9 +123,12 @@ public class AllowBindAppWidgetActivity extends AlertActivity implements return; } } + mAppWidgetManager = AppWidgetManager.getInstance(this); + final String widgetLabel = getWidgetLabel(); AlertController.AlertParams ap = mAlertParams; ap.mTitle = getString(R.string.allow_bind_app_widget_activity_allow_bind_title); - ap.mMessage = getString(R.string.allow_bind_app_widget_activity_allow_bind, label); + ap.mMessage = getString(R.string.allow_bind_app_widget_activity_allow_bind, label, + widgetLabel); ap.mPositiveButtonText = getString(R.string.create); ap.mNegativeButtonText = getString(android.R.string.cancel); ap.mPositiveButtonListener = this; @@ -133,18 +137,30 @@ public class AllowBindAppWidgetActivity extends AlertActivity implements (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null); mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse); - mAlwaysUse.setText(getString(R.string.allow_bind_app_widget_activity_always_allow_bind, label)); + mAlwaysUse.setText( + getString(R.string.allow_bind_app_widget_activity_always_allow_bind, label)); mAlwaysUse.setPadding(mAlwaysUse.getPaddingLeft(), mAlwaysUse.getPaddingTop(), mAlwaysUse.getPaddingRight(), (int) (mAlwaysUse.getPaddingBottom() + - getResources().getDimension(R.dimen.bind_app_widget_dialog_checkbox_bottom_padding))); + getResources().getDimension( + R.dimen.bind_app_widget_dialog_checkbox_bottom_padding))); - mAppWidgetManager = AppWidgetManager.getInstance(this); mAlwaysUse.setChecked(mAppWidgetManager.hasBindAppWidgetPermission(mCallingPackage, mProfile.getIdentifier())); setupAlert(); } + + private String getWidgetLabel() { + String label = ""; + for (AppWidgetProviderInfo providerInfo : mAppWidgetManager.getInstalledProviders()) { + if (providerInfo.provider.equals(mComponentName)) { + label = providerInfo.loadLabel(getPackageManager()); + break; + } + } + return label; + } } 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; + } +} diff --git a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java index c782b66c677..8e65605eecc 100644 --- a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java +++ b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java @@ -52,6 +52,7 @@ import com.android.settingslib.DeviceInfoUtils; import com.google.common.collect.ImmutableMap; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -108,18 +109,18 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen mSubId = getArguments().getInt(KEY_SUBSCRIPTION_ID); Resources res = context.getResources(); mLightDarkMap = ImmutableMap.builder() - .put(res.getInteger(R.color.SIM_color_teal), - res.getInteger(R.color.SIM_dark_mode_color_teal)) - .put(res.getInteger(R.color.SIM_color_blue), + .put(res.getInteger(R.color.SIM_color_cyan), + res.getInteger(R.color.SIM_dark_mode_color_cyan)) + .put(res.getInteger(R.color.SIM_color_blue800), res.getInteger(R.color.SIM_dark_mode_color_blue)) - .put(res.getInteger(R.color.SIM_color_indigo), - res.getInteger(R.color.SIM_dark_mode_color_indigo)) - .put(res.getInteger(R.color.SIM_color_purple), + .put(res.getInteger(R.color.SIM_color_green800), + res.getInteger(R.color.SIM_dark_mode_color_green)) + .put(res.getInteger(R.color.SIM_color_purple800), res.getInteger(R.color.SIM_dark_mode_color_purple)) - .put(res.getInteger(R.color.SIM_color_pink), + .put(res.getInteger(R.color.SIM_color_pink800), res.getInteger(R.color.SIM_dark_mode_color_pink)) - .put(res.getInteger(R.color.SIM_color_red), - res.getInteger(R.color.SIM_dark_mode_color_red)) + .put(res.getInteger(R.color.SIM_color_orange), + res.getInteger(R.color.SIM_dark_mode_color_orange)) .build(); } @@ -175,12 +176,7 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen final ColorAdapter adapter = new ColorAdapter(getContext(), R.layout.dialog_mobile_network_color_picker_item, mColors); mColorSpinner.setAdapter(adapter); - for (int i = 0; i < mColors.length; i++) { - if (mColors[i].getColor() == info.getIconTint()) { - mColorSpinner.setSelection(i); - break; - } - } + mColorSpinner.setSelection(getSimColorIndex(info.getIconTint())); final TextView operatorName = view.findViewById(R.id.operator_name_value); mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId); @@ -239,7 +235,7 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen private Color[] getColors() { final Resources res = getContext().getResources(); - final int[] colorInts = res.getIntArray(com.android.internal.R.array.sim_colors); + final int[] colorInts = res.getIntArray(R.array.sim_color_light); final String[] colorStrings = res.getStringArray(R.array.color_picker); final int iconSize = res.getDimensionPixelSize(R.dimen.color_swatch_size); final int strokeWidth = res.getDimensionPixelSize(R.dimen.color_swatch_stroke_width); @@ -286,4 +282,31 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen private int getDarkColor(int lightColor) { return mLightDarkMap.getOrDefault(lightColor, lightColor); } + + /* + * Get the color index from previous color that defined in Android OS + * (frameworks/base/core/res/res/values/arrays.xml). If can't find the color, continue to look + * for it in the new color plattee. If not, give it the first index. + */ + + private int getSimColorIndex(int color) { + int index = -1; + final int[] previousSimColorInts = + getContext().getResources().getIntArray(com.android.internal.R.array.sim_colors); + for (int i = 0; i < previousSimColorInts.length; i++) { + if (previousSimColorInts[i] == color) { + index = i; + } + } + + if (index == -1) { + for (int i = 0; i < mColors.length; i++) { + if (mColors[i].getColor() == color) { + index = i; + } + } + } + + return index == -1 ? 0 : index; + } } diff --git a/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java b/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java index d0df92ec8a7..70b05981370 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java @@ -159,7 +159,7 @@ public class RenameMobileNetworkDialogFragmentTest { eq(SubscriptionManager.NAME_SOURCE_USER_INPUT)); assertThat(captor.getValue()).isEqualTo("test2"); verify(mSubscriptionMgr) - .setIconTint(eq(Color.parseColor("#ff00796b" /* teal */)), eq(mSubscriptionId)); + .setIconTint(eq(Color.parseColor("#ff006D74" /* cyan */)), eq(mSubscriptionId)); } @Test @@ -174,6 +174,34 @@ public class RenameMobileNetworkDialogFragmentTest { assertThat(view.findViewById(R.id.number_label).getVisibility()).isEqualTo(View.GONE); } + @Test + public void populateView_getPreviousSimColor_setCorrectSelection() { + final View view = LayoutInflater.from(mActivity).inflate( + R.layout.dialog_mobile_network_rename, null); + when(mSubscriptionInfo.getIconTint()) + .thenReturn(Color.parseColor("#ff3367d6"/* blue700 */)); + + startDialog(); + mFragment.populateView(view); + + final Spinner colorSpinnerView = mFragment.getColorSpinnerView(); + assertThat(colorSpinnerView.getSelectedItemPosition()).isEqualTo(1); + } + + @Test + public void populateView_getUpdatedSimColor_setCorrectSelection() { + final View view = LayoutInflater.from(mActivity).inflate( + R.layout.dialog_mobile_network_rename, null); + when(mSubscriptionInfo.getIconTint()) + .thenReturn(Color.parseColor("#ff137333"/* Green800 */)); + + startDialog(); + mFragment.populateView(view); + + final Spinner colorSpinnerView = mFragment.getColorSpinnerView(); + assertThat(colorSpinnerView.getSelectedItemPosition()).isEqualTo(2); + } + /** * Helper method to start the dialog */