diff options
author | Hai Zhang <zhanghai@google.com> | 2019-03-28 15:29:40 -0700 |
---|---|---|
committer | Hai Zhang <zhanghai@google.com> | 2019-03-28 18:16:49 -0700 |
commit | 059640e4c0799c0b11bf45ba418a6b5bf8fbef20 (patch) | |
tree | 8cff49c2fa9a1ba3c750721907eaf56805118078 | |
parent | de639fe530787fbfd04ab2013cdb2aa6da65246a (diff) | |
download | android_packages_apps_PackageInstaller-059640e4c0799c0b11bf45ba418a6b5bf8fbef20.tar.gz android_packages_apps_PackageInstaller-059640e4c0799c0b11bf45ba418a6b5bf8fbef20.tar.bz2 android_packages_apps_PackageInstaller-059640e4c0799c0b11bf45ba418a6b5bf8fbef20.zip |
Add settings button for home role.
This was in DefaultHomePreferenceController.
Bug: 128713569
Test: manual
Change-Id: I98fc78c3700a871ee223d53fea227047f023589d
19 files changed, 473 insertions, 25 deletions
diff --git a/res/drawable/ic_info_outline.xml b/res/drawable/ic_info_outline.xml index 7b9e17e6..b57df449 100644 --- a/res/drawable/ic_info_outline.xml +++ b/res/drawable/ic_info_outline.xml @@ -22,9 +22,9 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24" - android:tint="?android:attr/colorControlNormal"> + android:tint="?android:colorControlNormal"> <path android:fillColor="#FF000000" - android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/> + android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z" /> </vector> diff --git a/res/drawable/ic_settings_accent.xml b/res/drawable/ic_settings_outline.xml index fd826b34..fd826b34 100644 --- a/res/drawable/ic_settings_accent.xml +++ b/res/drawable/ic_settings_outline.xml diff --git a/res/drawable/ic_settings_outline_accent.xml b/res/drawable/ic_settings_outline_accent.xml new file mode 100644 index 00000000..06aefa8d --- /dev/null +++ b/res/drawable/ic_settings_outline_accent.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + ~ Copyright (C) 2019 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. + --> + +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?android:colorAccent"> + + <path + android:fillColor="#FF000000" + android:pathData="M13.85,22.25h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.53c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46c0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19C1.98,9.9 1.83,9.09 2.2,8.47l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73c0.26,-0.17 0.52,-0.32 0.78,-0.46l0.27,-1.91c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91C15.21,21.71 14.59,22.25 13.85,22.25zM13.32,20.72c0,0.01 0,0.01 0,0.02L13.32,20.72zM10.68,20.7l0,0.02C10.69,20.72 10.69,20.71 10.68,20.7zM10.62,20.25h2.76l0.37,-2.55l0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34l2.38,0.96l1.38,-2.4l-2.03,-1.58l0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78c0,-0.27 -0.03,-0.53 -0.06,-0.78l-0.07,-0.56l2.03,-1.58l-1.39,-2.4l-2.39,0.96l-0.45,-0.35c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77L13.75,6.3l-0.37,-2.55h-2.76L10.25,6.3L9.72,6.51C9.28,6.7 8.84,6.95 8.38,7.3L7.93,7.63L5.55,6.68L4.16,9.07l2.03,1.58l-0.07,0.56C6.09,11.47 6.06,11.74 6.06,12c0,0.26 0.02,0.53 0.06,0.78l0.07,0.56l-2.03,1.58l1.38,2.4l2.39,-0.96l0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22L10.62,20.25zM18.22,17.72c0,0.01 -0.01,0.02 -0.01,0.03L18.22,17.72zM5.77,17.71l0.01,0.02C5.78,17.72 5.77,17.71 5.77,17.71zM3.93,9.47L3.93,9.47C3.93,9.47 3.93,9.47 3.93,9.47zM18.22,6.27c0,0.01 0.01,0.02 0.01,0.02L18.22,6.27zM5.79,6.25L5.78,6.27C5.78,6.27 5.79,6.26 5.79,6.25zM13.31,3.28c0,0.01 0,0.01 0,0.02L13.31,3.28zM10.69,3.26l0,0.02C10.69,3.27 10.69,3.27 10.69,3.26z" /> + + <path + android:fillColor="#FF000000" + android:pathData="M12,12m-3.5,0a3.5,3.5 0,1 1,7 0a3.5,3.5 0,1 1,-7 0" /> +</vector> diff --git a/res/layout/preference_widget_radio_button.xml b/res/layout/radio_button_preference_widget.xml index cd2a2ce4..cd2a2ce4 100644 --- a/res/layout/preference_widget_radio_button.xml +++ b/res/layout/radio_button_preference_widget.xml diff --git a/res/layout/settings_button_preference_widget.xml b/res/layout/settings_button_preference_widget.xml new file mode 100644 index 00000000..bd1d29b2 --- /dev/null +++ b/res/layout/settings_button_preference_widget.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + ~ Copyright (C) 2019 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. + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:orientation="horizontal"> + + <View + android:layout_width="1dp" + android:layout_height="match_parent" + android:layout_marginTop="16dp" + android:layout_marginBottom="16dp" + android:background="?android:listDivider" /> + + <ImageButton + android:id="@+id/settings_button" + android:layout_width="wrap_content" + android:minWidth="64dp" + android:layout_height="match_parent" + android:paddingStart="?android:listPreferredItemPaddingEnd" + android:paddingEnd="?android:listPreferredItemPaddingEnd" + android:background="?android:selectableItemBackground" + android:contentDescription="@string/settings_button" + android:scaleType="center" + android:src="@drawable/ic_settings_outline_accent" /> +</LinearLayout> diff --git a/res/layout/two_target_preference.xml b/res/layout/two_target_preference.xml new file mode 100644 index 00000000..4e3fce9e --- /dev/null +++ b/res/layout/two_target_preference.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + ~ Copyright (C) 2019 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. + --> + +<!-- The transparent background prevents PreferenceGroupAdapter from adding a background. --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@android:color/transparent"> + + <include + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + layout="@layout/preference_material" /> +</LinearLayout> diff --git a/res/values/strings.xml b/res/values/strings.xml index 34c8a2d5..b58c0a60 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -712,6 +712,9 @@ <!-- Separator for permissions, before last type. Include spaces before and after if needed [CHAR LIMIT=10] --> <string name="ongoing_usage_dialog_last_separator">\u0020and\u0020</string> + <!-- Accessibility label for button that opens a settings screen [CHAR LIMIT=NONE] --> + <string name="settings_button">Settings</string> + <!-- Title for page of managing default apps. [CHAR LIMIT=30] --> <string name="default_apps">Default apps</string> diff --git a/src/com/android/packageinstaller/permission/ui/handheld/PermissionUsageFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/PermissionUsageFragment.java index 7c7fbdcc..7e5b1b79 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/PermissionUsageFragment.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/PermissionUsageFragment.java @@ -662,7 +662,7 @@ public class PermissionUsageFragment extends SettingsWithLargeHeader implements pref.setTitleIcons(Collections.singletonList(group.getIconResId())); pref.setKey(group.getApp().packageName + "," + group.getName()); pref.useSmallerIcon(); - pref.setRightIcon(context.getDrawable(R.drawable.ic_settings_accent)); + pref.setRightIcon(context.getDrawable(R.drawable.ic_settings_outline)); return pref; } diff --git a/src/com/android/packageinstaller/role/model/HomeRoleBehavior.java b/src/com/android/packageinstaller/role/model/HomeRoleBehavior.java index 9c18fe36..1fcf1774 100644 --- a/src/com/android/packageinstaller/role/model/HomeRoleBehavior.java +++ b/src/com/android/packageinstaller/role/model/HomeRoleBehavior.java @@ -16,19 +16,25 @@ package com.android.packageinstaller.role.model; +import android.app.role.RoleManager; +import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Build; import android.os.UserHandle; import android.provider.Settings; +import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.preference.Preference; +import com.android.packageinstaller.permission.utils.CollectionUtils; +import com.android.packageinstaller.role.ui.SettingsButtonPreference; import com.android.packageinstaller.role.utils.UserUtils; import com.android.permissioncontroller.R; @@ -44,6 +50,8 @@ import java.util.Objects; */ public class HomeRoleBehavior implements RoleBehavior { + private static final String LOG_TAG = HomeRoleBehavior.class.getSimpleName(); + @Override public boolean isAvailableAsUser(@NonNull Role role, @NonNull UserHandle user, @NonNull Context context) { @@ -91,6 +99,34 @@ public class HomeRoleBehavior implements RoleBehavior { } @Override + public void preparePreferenceAsUser(@NonNull Role role, + @NonNull SettingsButtonPreference preference, @NonNull UserHandle user, + @NonNull Context context) { + SettingsButtonPreference.OnSettingsButtonClickListener listener = null; + RoleManager roleManager = context.getSystemService(RoleManager.class); + String packageName = CollectionUtils.firstOrNull(roleManager.getRoleHoldersAsUser( + role.getName(), user)); + if (packageName != null) { + Intent intent = new Intent(Intent.ACTION_APPLICATION_PREFERENCES) + .setPackage(packageName) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + PackageManager userPackageManager = UserUtils.getUserContext(context, user) + .getPackageManager(); + ActivityInfo activityInfo = intent.resolveActivityInfo(userPackageManager, 0); + if (activityInfo != null && activityInfo.exported) { + listener = preference2 -> { + try { + context.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.e(LOG_TAG, "Cannot start activity for home app preferences", e); + } + }; + } + } + preference.setOnSettingsButtonClickListener(listener); + } + + @Override public void prepareApplicationPreferenceAsUser(@NonNull Role role, @NonNull Preference preference, @NonNull ApplicationInfo applicationInfo, @NonNull UserHandle user, @NonNull Context context) { diff --git a/src/com/android/packageinstaller/role/model/Role.java b/src/com/android/packageinstaller/role/model/Role.java index c498457a..d5cd7cbd 100644 --- a/src/com/android/packageinstaller/role/model/Role.java +++ b/src/com/android/packageinstaller/role/model/Role.java @@ -35,6 +35,7 @@ import androidx.preference.Preference; import com.android.packageinstaller.Constants; import com.android.packageinstaller.permission.utils.Utils; +import com.android.packageinstaller.role.ui.SettingsButtonPreference; import com.android.packageinstaller.role.utils.PackageUtils; import com.android.packageinstaller.role.utils.UserUtils; @@ -342,6 +343,20 @@ public class Role { } /** + * Prepare a {@link Preference} for this role. + * + * @param preference the {@link Preference} for this role + * @param user the user for this role + * @param context the {@code Context} to retrieve system services + */ + public void preparePreferenceAsUser(@NonNull SettingsButtonPreference preference, + @NonNull UserHandle user, @NonNull Context context) { + if (mBehavior != null) { + mBehavior.preparePreferenceAsUser(this, preference, user, context); + } + } + + /** * Prepare a {@link Preference} for an application. * * @param preference the {@link Preference} for the application diff --git a/src/com/android/packageinstaller/role/model/RoleBehavior.java b/src/com/android/packageinstaller/role/model/RoleBehavior.java index fa672f48..4701c20e 100644 --- a/src/com/android/packageinstaller/role/model/RoleBehavior.java +++ b/src/com/android/packageinstaller/role/model/RoleBehavior.java @@ -25,6 +25,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.preference.Preference; +import com.android.packageinstaller.role.ui.SettingsButtonPreference; + import java.util.Collections; import java.util.List; @@ -75,6 +77,13 @@ public interface RoleBehavior { } /** + * @see Role#preparePreferenceAsUser(SettingsButtonPreference, UserHandle, Context) + */ + default void preparePreferenceAsUser(@NonNull Role role, + @NonNull SettingsButtonPreference preference, @NonNull UserHandle user, + @NonNull Context context) {} + + /** * @see Role#prepareApplicationPreferenceAsUser(Preference, ApplicationInfo, UserHandle, * Context) */ diff --git a/src/com/android/packageinstaller/role/ui/AppIconSettingsButtonPreference.java b/src/com/android/packageinstaller/role/ui/AppIconSettingsButtonPreference.java new file mode 100644 index 00000000..a6dd496c --- /dev/null +++ b/src/com/android/packageinstaller/role/ui/AppIconSettingsButtonPreference.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2019 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.packageinstaller.role.ui; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.preference.PreferenceViewHolder; + +/** + * {@link SettingsButtonPreference} with {@link AppIconPreference.Mixin}. + */ +public class AppIconSettingsButtonPreference extends SettingsButtonPreference { + + private AppIconPreference.Mixin mMixin; + + public AppIconSettingsButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs, + @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + + init(); + } + + public AppIconSettingsButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs, + @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + + init(); + } + + public AppIconSettingsButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + + init(); + } + + public AppIconSettingsButtonPreference(@NonNull Context context) { + super(context); + + init(); + } + + private void init() { + mMixin = new AppIconPreference.Mixin(getContext()); + } + + @Override + public void onBindViewHolder(@NonNull PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + mMixin.onBindViewHolder(holder); + } +} diff --git a/src/com/android/packageinstaller/role/ui/DefaultAppListFragment.java b/src/com/android/packageinstaller/role/ui/DefaultAppListFragment.java index 968464be..0d85abe2 100644 --- a/src/com/android/packageinstaller/role/ui/DefaultAppListFragment.java +++ b/src/com/android/packageinstaller/role/ui/DefaultAppListFragment.java @@ -158,9 +158,10 @@ public class DefaultAppListFragment extends SettingsFragment RoleItem roleItem = roleItems.get(i); Role role = roleItem.getRole(); - Preference preference = oldPreferences.get(role.getName()); + AppIconSettingsButtonPreference preference = + (AppIconSettingsButtonPreference) oldPreferences.get(role.getName()); if (preference == null) { - preference = new AppIconPreference(context); + preference = new AppIconSettingsButtonPreference(context); preference.setKey(role.getName()); preference.setIconSpaceReserved(true); preference.setTitle(role.getShortLabelResource()); @@ -178,6 +179,7 @@ public class DefaultAppListFragment extends SettingsFragment preference.setIcon(Utils.getBadgedIcon(context, holderApplicationInfo)); preference.setSummary(Utils.getAppLabel(holderApplicationInfo, context)); } + role.preparePreferenceAsUser(preference, user, context); preferenceGroup.addPreference(preference); } diff --git a/src/com/android/packageinstaller/role/ui/FooterPreference.java b/src/com/android/packageinstaller/role/ui/FooterPreference.java index 4c8a8449..cca4d347 100644 --- a/src/com/android/packageinstaller/role/ui/FooterPreference.java +++ b/src/com/android/packageinstaller/role/ui/FooterPreference.java @@ -19,7 +19,7 @@ package com.android.packageinstaller.role.ui; import android.content.Context; import android.util.AttributeSet; import android.view.Gravity; -import android.view.ViewGroup; +import android.view.View; import android.widget.LinearLayout; import androidx.annotation.AttrRes; @@ -76,14 +76,14 @@ public class FooterPreference extends Preference { holder.setDividerAllowedAbove(true); - ViewGroup iconLayout = (ViewGroup) holder.findViewById(R.id.icon_frame); - LinearLayout.LayoutParams iconLayoutParams = (LinearLayout.LayoutParams) - iconLayout.getLayoutParams(); - iconLayoutParams.gravity = Gravity.TOP; - iconLayout.setLayoutParams(iconLayoutParams); - int iconLayoutPaddingVertical = UiUtils.dpToPxOffset(ICON_LAYOUT_PADDING_VERTICAL_DP, - iconLayout.getContext()); - iconLayout.setPaddingRelative(iconLayout.getPaddingStart(), iconLayoutPaddingVertical, - iconLayout.getPaddingEnd(), iconLayoutPaddingVertical); + View iconFrame = holder.findViewById(R.id.icon_frame); + LinearLayout.LayoutParams iconFrameLayoutParams = (LinearLayout.LayoutParams) + iconFrame.getLayoutParams(); + iconFrameLayoutParams.gravity = Gravity.TOP; + iconFrame.setLayoutParams(iconFrameLayoutParams); + int iconFramePaddingVertical = UiUtils.dpToPxOffset(ICON_LAYOUT_PADDING_VERTICAL_DP, + iconFrame.getContext()); + iconFrame.setPaddingRelative(iconFrame.getPaddingStart(), iconFramePaddingVertical, + iconFrame.getPaddingEnd(), iconFramePaddingVertical); } } diff --git a/src/com/android/packageinstaller/role/ui/RadioButtonPreference.java b/src/com/android/packageinstaller/role/ui/RadioButtonPreference.java index 95d091d8..8f75c615 100644 --- a/src/com/android/packageinstaller/role/ui/RadioButtonPreference.java +++ b/src/com/android/packageinstaller/role/ui/RadioButtonPreference.java @@ -18,6 +18,7 @@ package com.android.packageinstaller.role.ui; import android.content.Context; import android.util.AttributeSet; +import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.RadioButton; @@ -47,6 +48,8 @@ public class RadioButtonPreference extends TwoStatePreference { } public RadioButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs) { + // TwoStatePreference(Context, AttributeSet) breaks the default style attribute in + // Preference(Context, AttributeSet), so we need to add it back here. this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.preferenceStyle, android.R.attr.preferenceStyle)); } @@ -60,22 +63,22 @@ public class RadioButtonPreference extends TwoStatePreference { @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - setWidgetLayoutResource(R.layout.preference_widget_radio_button); + setWidgetLayoutResource(R.layout.radio_button_preference_widget); } @Override public void onBindViewHolder(@NonNull PreferenceViewHolder holder) { super.onBindViewHolder(holder); - ViewGroup viewGroup = (ViewGroup) holder.itemView; - ViewGroup widgetFrame = (ViewGroup) holder.findViewById(android.R.id.widget_frame); - if (viewGroup.indexOfChild(widgetFrame) != 0) { + ViewGroup itemView = (ViewGroup) holder.itemView; + View widgetFrame = holder.findViewById(android.R.id.widget_frame); + if (itemView.indexOfChild(widgetFrame) != 0) { widgetFrame.setPaddingRelative(widgetFrame.getPaddingEnd(), widgetFrame.getPaddingTop(), widgetFrame.getPaddingStart(), widgetFrame.getPaddingBottom()); - viewGroup.removeView(widgetFrame); - viewGroup.addView(widgetFrame, 0); - viewGroup.setPaddingRelative(0, viewGroup.getPaddingTop(), viewGroup.getPaddingEnd(), - viewGroup.getPaddingBottom()); + itemView.removeView(widgetFrame); + itemView.addView(widgetFrame, 0); + itemView.setPaddingRelative(0, itemView.getPaddingTop(), itemView.getPaddingEnd(), + itemView.getPaddingBottom()); } RadioButton radioButton = (RadioButton) holder.findViewById(R.id.radio_button); diff --git a/src/com/android/packageinstaller/role/ui/SettingsButtonPreference.java b/src/com/android/packageinstaller/role/ui/SettingsButtonPreference.java new file mode 100644 index 00000000..e6350837 --- /dev/null +++ b/src/com/android/packageinstaller/role/ui/SettingsButtonPreference.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2019 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.packageinstaller.role.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +import com.android.permissioncontroller.R; + +/** + * {@link Preference} with a settings button. + * + * @see com.android.settings.widget.GearPreference + */ +public class SettingsButtonPreference extends TwoTargetPreference { + + @Nullable + private OnSettingsButtonClickListener mOnSettingsButtonClickListener; + + public SettingsButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs, + @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + + init(); + } + + public SettingsButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs, + @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + + init(); + } + + public SettingsButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + + init(); + } + + public SettingsButtonPreference(@NonNull Context context) { + super(context); + + init(); + } + + private void init() { + setWidgetLayoutResource(R.layout.settings_button_preference_widget); + } + + /** + * Set the listener for settings button click. + * + * @param listener the listener + */ + public void setOnSettingsButtonClickListener(@Nullable OnSettingsButtonClickListener listener) { + mOnSettingsButtonClickListener = listener; + notifyChanged(); + } + + @Override + public void onBindViewHolder(@NonNull PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + View widgetFrame = holder.findViewById(android.R.id.widget_frame); + widgetFrame.setPadding(0, 0, 0, 0); + View settingsButton = holder.findViewById(R.id.settings_button); + if (mOnSettingsButtonClickListener != null) { + widgetFrame.setVisibility(View.VISIBLE); + settingsButton.setOnClickListener(view -> + mOnSettingsButtonClickListener.onSettingsButtonClick(this)); + } else { + widgetFrame.setVisibility(View.GONE); + settingsButton.setOnClickListener(null); + } + // Make the settings button enabled even if the preference itself is disabled. + settingsButton.setEnabled(true); + } + + /** + * Listener for settings button click. + */ + public interface OnSettingsButtonClickListener { + + /** + * Callback when settings button is clicked. + * + * @param preference the {@link SettingsButtonPreference} that was clicked + */ + void onSettingsButtonClick(@NonNull SettingsButtonPreference preference); + } +} diff --git a/src/com/android/packageinstaller/role/ui/SpecialAppAccessFragment.java b/src/com/android/packageinstaller/role/ui/SpecialAppAccessFragment.java index c7461e6a..0fb0e37e 100644 --- a/src/com/android/packageinstaller/role/ui/SpecialAppAccessFragment.java +++ b/src/com/android/packageinstaller/role/ui/SpecialAppAccessFragment.java @@ -149,6 +149,9 @@ public class SpecialAppAccessFragment extends SettingsFragment } preference.setChecked(isHolderPackage); + UserHandle user = UserHandle.getUserHandleForUid(qualifyingApplicationInfo.uid); + mRole.prepareApplicationPreferenceAsUser(preference, qualifyingApplicationInfo, user, + context); preferenceScreen.addPreference(preference); } diff --git a/src/com/android/packageinstaller/role/ui/SpecialAppAccessListFragment.java b/src/com/android/packageinstaller/role/ui/SpecialAppAccessListFragment.java index 11ecd766..518e882c 100644 --- a/src/com/android/packageinstaller/role/ui/SpecialAppAccessListFragment.java +++ b/src/com/android/packageinstaller/role/ui/SpecialAppAccessListFragment.java @@ -102,9 +102,10 @@ public class SpecialAppAccessListFragment extends SettingsFragment RoleItem roleItem = roleItems.get(i); Role role = roleItem.getRole(); - Preference preference = oldPreferences.get(role.getName()); + AppIconSettingsButtonPreference preference = + (AppIconSettingsButtonPreference) oldPreferences.get(role.getName()); if (preference == null) { - preference = new AppIconPreference(context); + preference = new AppIconSettingsButtonPreference(context); preference.setKey(role.getName()); preference.setIconSpaceReserved(true); preference.setTitle(role.getShortLabelResource()); @@ -112,6 +113,8 @@ public class SpecialAppAccessListFragment extends SettingsFragment preference.setOnPreferenceClickListener(this); } + role.preparePreferenceAsUser(preference, Process.myUserHandle(), context); + preferenceScreen.addPreference(preference); } diff --git a/src/com/android/packageinstaller/role/ui/TwoTargetPreference.java b/src/com/android/packageinstaller/role/ui/TwoTargetPreference.java new file mode 100644 index 00000000..0d49bb4a --- /dev/null +++ b/src/com/android/packageinstaller/role/ui/TwoTargetPreference.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 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.packageinstaller.role.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +import com.android.permissioncontroller.R; + +/** + * {@link Preference} with the widget layout as a separate target. + * + * @see com.android.settingslib.TwoTargetPreference + */ +public class TwoTargetPreference extends Preference { + + public TwoTargetPreference(@NonNull Context context, @Nullable AttributeSet attrs, + @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + + init(); + } + + public TwoTargetPreference(@NonNull Context context, @Nullable AttributeSet attrs, + @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + + init(); + } + + public TwoTargetPreference(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + + init(); + } + + public TwoTargetPreference(@NonNull Context context) { + super(context); + + init(); + } + + private void init() { + setLayoutResource(R.layout.two_target_preference); + } + + @Override + public void onBindViewHolder(@NonNull PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + View widgetFrame = holder.findViewById(android.R.id.widget_frame); + ViewGroup widgetFrameParent = (ViewGroup) widgetFrame.getParent(); + ViewGroup itemView = (ViewGroup) holder.itemView; + if (widgetFrameParent != itemView) { + widgetFrameParent.removeView(widgetFrame); + itemView.addView(widgetFrame); + } + } +} |