diff options
8 files changed, 66 insertions, 45 deletions
diff --git a/res/layout/request_role_view.xml b/res/layout/request_role_view.xml index f0b86df9..44430a5f 100644 --- a/res/layout/request_role_view.xml +++ b/res/layout/request_role_view.xml @@ -16,12 +16,16 @@ ~ limitations under the License. --> -<FrameLayout +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/RequestRoleView"> + <ListView + android:id="@+id/list" + style="@style/RequestRoleViewListView" /> + <CheckBox android:id="@+id/dont_ask_again" android:text="@string/request_role_dont_ask_again" style="@style/RequestRoleViewCheckbox" /> -</FrameLayout> +</LinearLayout> diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml index 82708ed7..6d0dda5a 100644 --- a/res/values/overlayable.xml +++ b/res/values/overlayable.xml @@ -164,6 +164,7 @@ <!-- START REQUEST ROLE DIALOG VIEW --> <item type="style" name="RequestRoleView" /> + <item type="style" name="RequestRoleViewListView" /> <item type="style" name="RequestRoleViewCheckbox" /> <!-- END REQUEST ROLE DIALOG VIEW --> diff --git a/res/values/styles.xml b/res/values/styles.xml index 6469cbd9..5516dbe3 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -711,15 +711,26 @@ <style name="RequestRoleView"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> - <item name="android:paddingStart">?android:dialogPreferredPadding</item> - <item name="android:paddingEnd">?android:dialogPreferredPadding</item> - <item name="android:clipChildren">false</item> - <item name="android:clipToPadding">false</item> + <!-- @android:dimen/dialog_title_divider_material --> + <item name="android:paddingTop">8dp</item> + <item name="android:orientation">vertical</item> + </style> + + <style name="RequestRoleViewListView"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">0dp</item> + <item name="android:layout_weight">1</item> + <item name="android:cacheColorHint">@null</item> + <item name="android:divider">?android:listDividerAlertDialog</item> + <item name="android:overScrollMode">ifContentScrolls</item> + <item name="android:scrollIndicators">top|bottom</item> </style> <style name="RequestRoleViewCheckbox"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> + <item name="android:layout_marginStart">?android:dialogPreferredPadding</item> + <item name="android:layout_marginEnd">?android:dialogPreferredPadding</item> <item name="android:minHeight">?android:listPreferredItemHeightSmall</item> <item name="android:paddingStart">16dp</item> <item name="android:textAppearance">@style/android:TextAppearance.Material.Subhead</item> diff --git a/res/values/themes.xml b/res/values/themes.xml index 5db43f7c..b8ed550a 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -55,6 +55,7 @@ <style name="RequestRole" parent="android:Theme.DeviceDefault.Settings"> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:navigationBarColor">@android:color/transparent</item> + <item name="android:navigationBarDividerColor">@null</item> <item name="android:statusBarColor">@android:color/transparent</item> <item name="android:windowActionBar">false</item> <item name="android:windowAnimationStyle">@null</item> @@ -62,6 +63,8 @@ <item name="android:windowContentOverlay">@null</item> <item name="android:windowDisablePreview">true</item> <item name="android:windowIsTranslucent">true</item> + <item name="android:windowLightNavigationBar">false</item> + <item name="android:windowLightStatusBar">false</item> <item name="android:windowNoTitle">true</item> </style> diff --git a/src/com/android/packageinstaller/permission/service/PermissionControllerServiceImpl.java b/src/com/android/packageinstaller/permission/service/PermissionControllerServiceImpl.java index 6427ba36..d846ce09 100644 --- a/src/com/android/packageinstaller/permission/service/PermissionControllerServiceImpl.java +++ b/src/com/android/packageinstaller/permission/service/PermissionControllerServiceImpl.java @@ -67,9 +67,8 @@ import java.util.function.IntConsumer; /** * Calls from the system into the permission controller. * - * All methods are called async beside the backup related method. For these we force to use the - * async-task single thread executor so that multiple parallel backups don't override the delayed - * the backup state racily. + * All reading methods are called async, and all writing method are called on the AsyncTask single + * thread executor so that multiple writes won't override each other concurrently. */ public final class PermissionControllerServiceImpl extends PermissionControllerService { private static final String LOG_TAG = PermissionControllerServiceImpl.class.getSimpleName(); @@ -210,8 +209,8 @@ public final class PermissionControllerServiceImpl extends PermissionControllerS public void onRevokeRuntimePermissions(@NonNull Map<String, List<String>> request, boolean doDryRun, int reason, @NonNull String callerPackageName, @NonNull Consumer<Map<String, List<String>>> callback) { - AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> callback.accept( - onRevokeRuntimePermissions(request, doDryRun, reason, callerPackageName))); + AsyncTask.execute(() -> callback.accept(onRevokeRuntimePermissions(request, doDryRun, + reason, callerPackageName))); } private @NonNull Map<String, List<String>> onRevokeRuntimePermissions( @@ -403,7 +402,7 @@ public final class PermissionControllerServiceImpl extends PermissionControllerS @Override public void onRevokeRuntimePermission(@NonNull String packageName, @NonNull String permissionName, @NonNull Runnable callback) { - AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { + AsyncTask.execute(() -> { onRevokeRuntimePermission(packageName, permissionName); callback.run(); }); @@ -503,9 +502,8 @@ public final class PermissionControllerServiceImpl extends PermissionControllerS public void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName, @NonNull String packageName, @NonNull String unexpandedPermission, int grantState, @NonNull Consumer<Boolean> callback) { - AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> callback.accept( - onSetRuntimePermissionGrantStateByDeviceAdmin(callerPackageName, packageName, - unexpandedPermission, grantState))); + AsyncTask.execute(() -> callback.accept(onSetRuntimePermissionGrantStateByDeviceAdmin( + callerPackageName, packageName, unexpandedPermission, grantState))); } private boolean onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName, @@ -568,7 +566,7 @@ public final class PermissionControllerServiceImpl extends PermissionControllerS @Override public void onGrantOrUpgradeDefaultRuntimePermissions(@NonNull Runnable callback) { - AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { + AsyncTask.execute(() -> { onGrantOrUpgradeDefaultRuntimePermissions(); callback.run(); }); diff --git a/src/com/android/packageinstaller/permission/ui/handheld/ReviewPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/ReviewPermissionsFragment.java index 85ec2d32..6c3e224c 100644 --- a/src/com/android/packageinstaller/permission/ui/handheld/ReviewPermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/handheld/ReviewPermissionsFragment.java @@ -121,6 +121,7 @@ public final class ReviewPermissionsFragment extends PreferenceFragmentCompat // If the system called for a review but no groups are found, this means that all groups // are restricted. Hence there is nothing to review and instantly continue. confirmPermissionsReview(); + executeCallback(true); activity.finish(); } } @@ -188,7 +189,10 @@ public final class ReviewPermissionsFragment extends PreferenceFragmentCompat preferenceGroups.add(mNewPermissionsCategory); preferenceGroups.add(mCurrentPermissionsCategory); } else { - preferenceGroups.add(getPreferenceScreen()); + PreferenceScreen preferenceScreen = getPreferenceScreen(); + if (preferenceScreen != null) { + preferenceGroups.add(preferenceScreen); + } } final int preferenceGroupCount = preferenceGroups.size(); diff --git a/src/com/android/packageinstaller/role/model/BrowserRoleBehavior.java b/src/com/android/packageinstaller/role/model/BrowserRoleBehavior.java index 56c7b7af..1534081f 100644 --- a/src/com/android/packageinstaller/role/model/BrowserRoleBehavior.java +++ b/src/com/android/packageinstaller/role/model/BrowserRoleBehavior.java @@ -105,9 +105,7 @@ public class BrowserRoleBehavior implements RoleBehavior { for (int i = 0; i < resolveInfosSize; i++) { ResolveInfo resolveInfo = resolveInfos.get(i); - if (!resolveInfo.handleAllWebDataURI || !resolveInfo.activityInfo.enabled - || !resolveInfo.activityInfo.applicationInfo.enabled - || resolveInfo.activityInfo.applicationInfo.isInstantApp()) { + if (!resolveInfo.handleAllWebDataURI) { continue; } packageNames.add(resolveInfo.activityInfo.packageName); diff --git a/src/com/android/packageinstaller/role/ui/RequestRoleFragment.java b/src/com/android/packageinstaller/role/ui/RequestRoleFragment.java index 55ea3dd1..7991a2fb 100644 --- a/src/com/android/packageinstaller/role/ui/RequestRoleFragment.java +++ b/src/com/android/packageinstaller/role/ui/RequestRoleFragment.java @@ -76,7 +76,9 @@ public class RequestRoleFragment extends DialogFragment { private Role mRole; + private ListView mListView; private Adapter mAdapter; + @Nullable private CheckBox mDontAskAgainCheck; private RequestRoleViewModel mViewModel; @@ -145,20 +147,27 @@ public class RequestRoleFragment extends DialogFragment { LayoutInflater inflater = LayoutInflater.from(context); View titleLayout = inflater.inflate(R.layout.request_role_title, null); - ImageView iconImage = titleLayout.findViewById(R.id.icon); + ImageView iconImage = titleLayout.requireViewById(R.id.icon); iconImage.setImageDrawable(icon); - TextView titleText = titleLayout.findViewById(R.id.title); + TextView titleText = titleLayout.requireViewById(R.id.title); titleText.setText(title); - mAdapter = new Adapter(mRole); + View viewLayout = inflater.inflate(R.layout.request_role_view, null); + mListView = viewLayout.requireViewById(R.id.list); + mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); + mListView.setOnItemClickListener((parent, view, position, id) -> onItemClicked(position)); + mAdapter = new Adapter(mListView, mRole); if (savedInstanceState != null) { mAdapter.onRestoreInstanceState(savedInstanceState); } + mListView.setAdapter(mAdapter); - View viewLayout = null; - if (UserDeniedManager.getInstance(context).isDeniedOnce(mRoleName, mPackageName)) { - viewLayout = inflater.inflate(R.layout.request_role_view, null); - mDontAskAgainCheck = viewLayout.findViewById(R.id.dont_ask_again); + CheckBox dontAskAgainCheck = viewLayout.requireViewById(R.id.dont_ask_again); + boolean isDeniedOnce = UserDeniedManager.getInstance(context).isDeniedOnce(mRoleName, + mPackageName); + dontAskAgainCheck.setVisibility(isDeniedOnce ? View.VISIBLE : View.GONE); + if (isDeniedOnce) { + mDontAskAgainCheck = dontAskAgainCheck; mDontAskAgainCheck.setOnClickListener(view -> updateUi()); if (savedInstanceState != null) { boolean dontAskAgain = savedInstanceState.getBoolean(STATE_DONT_ASK_AGAIN); @@ -169,8 +178,6 @@ public class RequestRoleFragment extends DialogFragment { AlertDialog dialog = builder .setCustomTitle(titleLayout) - .setSingleChoiceItems(mAdapter, AdapterView.INVALID_POSITION, (dialog2, which) -> - onItemClicked(which)) .setView(viewLayout) // Set the positive button listener later to avoid the automatic dismiss behavior. .setPositiveButton(R.string.request_role_set_as_default, null) @@ -216,8 +223,6 @@ public class RequestRoleFragment extends DialogFragment { }; mPackageRemovalMonitor.register(); - mAdapter.setListView(getDialog().getListView()); - // Postponed to onStart() so that the list view in dialog is created. mViewModel = ViewModelProviders.of(this, new RequestRoleViewModel.Factory(mRole, requireActivity().getApplication())).get(RequestRoleViewModel.class); @@ -333,12 +338,12 @@ public class RequestRoleFragment extends DialogFragment { } private void updateUi() { - AlertDialog dialog = getDialog(); boolean enabled = mViewModel.getManageRoleHolderStateLiveData().getValue() == ManageRoleHolderStateLiveData.STATE_IDLE; - dialog.getListView().setEnabled(enabled); + mListView.setEnabled(enabled); boolean dontAskAgain = mDontAskAgainCheck != null && mDontAskAgainCheck.isChecked(); mAdapter.setDontAskAgain(dontAskAgain); + AlertDialog dialog = getDialog(); dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled && (dontAskAgain || !mAdapter.isHolderApplicationChecked())); dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(enabled); @@ -465,6 +470,9 @@ public class RequestRoleFragment extends DialogFragment { private static final int LAYOUT_TRANSITION_DURATION_MILLIS = 150; @NonNull + private final ListView mListView; + + @NonNull private final Role mRole; // We'll use a null to represent the "None" item. @@ -474,8 +482,6 @@ public class RequestRoleFragment extends DialogFragment { private boolean mHasHolderApplication; - private ListView mListView; - private boolean mDontAskAgain; // If user has ever clicked an item to mark it as checked, we no longer automatically mark @@ -487,7 +493,8 @@ public class RequestRoleFragment extends DialogFragment { @Nullable private String mPendingUserCheckedPackageName; - Adapter(@NonNull Role role) { + Adapter(@NonNull ListView listView, @NonNull Role role) { + mListView = listView; mRole = role; } @@ -506,10 +513,6 @@ public class RequestRoleFragment extends DialogFragment { } } - public void setListView(@NonNull ListView listView) { - mListView = listView; - } - public void setDontAskAgain(boolean dontAskAgain) { if (mDontAskAgain == dontAskAgain) { return; @@ -732,11 +735,10 @@ public class RequestRoleFragment extends DialogFragment { public final TextView subtitleText; ViewHolder(@NonNull View view) { - iconImage = Objects.requireNonNull(view.findViewById(R.id.icon)); - titleAndSubtitleLayout = Objects.requireNonNull(view.findViewById( - R.id.title_and_subtitle)); - titleText = Objects.requireNonNull(view.findViewById(R.id.title)); - subtitleText = Objects.requireNonNull(view.findViewById(R.id.subtitle)); + iconImage = view.requireViewById(R.id.icon); + titleAndSubtitleLayout = view.requireViewById(R.id.title_and_subtitle); + titleText = view.requireViewById(R.id.title); + subtitleText = view.requireViewById(R.id.subtitle); } } } |