Implement new "Open by default" page

- Use the new MainSwitch and TopIntro widgets.
- Create VerifiedLinksPreference and LeftSideCheckBoxPreference.
- Create ProgressDialogFragment and SupportedLinksDialogFragment.
- Retrieve the links info from DomainVerificationManager.
- Allow user to change the supported links into selected links.
- Refactor the ClearDefaultsPreference.
- Move AppLaunchSettings into intentpicker directory.

Bug: 177923646
Bug: 182530528
Test: manual test
Change-Id: I935a2fdd0f62cdb8b8d3210fb2f800f682249cb7
This commit is contained in:
Sunny Shao
2021-03-05 19:51:08 +08:00
parent 01f77d8e00
commit 81fa20a4f1
21 changed files with 1478 additions and 183 deletions

View File

@@ -0,0 +1,211 @@
/*
* 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.applications.intentpicker;
import static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_NONE;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.verify.domain.DomainOwner;
import android.content.pm.verify.domain.DomainVerificationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProviders;
import com.android.settings.R;
import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** A customized {@link DialogFragment} with a progress bar. */
public class ProgressDialogFragment extends DialogFragment {
private static final String TAG = "ProgressDialogFragment";
private static final String DLG_ID = "ProgressDialog";
private static final int PROGRESS_BAR_STEPPING_TIME = 20;
private ProgressAlertDialog mProgressAlertDialog;
private DomainVerificationManager mDomainVerificationManager;
private List<SupportedLinkWrapper> mSupportedLinkWrapperList;
private SupportedLinkViewModel mViewModel;
private Handler mHandle;
private String mPackage;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = ViewModelProviders.of(this.getActivity()).get(SupportedLinkViewModel.class);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mPackage = getArguments().getString(AppLaunchSettings.APP_PACKAGE_KEY);
mDomainVerificationManager = getActivity().getSystemService(
DomainVerificationManager.class);
mHandle = new Handler(Looper.getMainLooper());
mProgressAlertDialog = createProgressAlertDialog();
return mProgressAlertDialog;
}
private ProgressAlertDialog createProgressAlertDialog() {
final Context context = getActivity();
final ProgressAlertDialog progressDialog = new ProgressAlertDialog(context);
final String title = context.getResources().getString(
R.string.app_launch_checking_links_title);
progressDialog.setTitle(IntentPickerUtils.getCentralizedDialogTitle(title));
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
context.getText(R.string.app_launch_dialog_cancel),
(dialog, which) -> {
if (which == DialogInterface.BUTTON_NEGATIVE) {
dialog.cancel();
}
});
progressDialog.setCanceledOnTouchOutside(true);
return progressDialog;
}
/** Display the {@link ProgressAlertDialog}. */
public void showDialog(FragmentManager manager) {
show(manager, DLG_ID);
}
@Override
public void onResume() {
super.onResume();
generateProgressAlertDialog();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mProgressAlertDialog != null && mProgressAlertDialog.isShowing()) {
mProgressAlertDialog.cancel();
}
}
/**
* To generate a progress alter dialog and invoke the supported links dialog.
*/
private void generateProgressAlertDialog() {
ThreadUtils.postOnBackgroundThread(() -> {
final long start = SystemClock.elapsedRealtime();
queryLinksInBackground();
IntentPickerUtils.logd(
"queryLinksInBackground take time: " + (SystemClock.elapsedRealtime() - start));
if (mProgressAlertDialog.isShowing()) {
mHandle.post(() -> {
synchronized (mHandle) {
if (mProgressAlertDialog.isShowing()) {
mProgressAlertDialog.dismiss();
IntentPickerUtils.logd("mProgressAlertDialog.dismiss() and isShowing: "
+ mProgressAlertDialog.isShowing());
launchSupportedLinksDialogFragment();
}
}
});
}
});
}
private void queryLinksInBackground() {
final List<String> links = IntentPickerUtils.getLinksList(mDomainVerificationManager,
mPackage, DOMAIN_STATE_NONE);
final int linksNo = links.size();
int index = 0;
mSupportedLinkWrapperList = new ArrayList<>();
for (String host : links) {
final List<DomainOwner> ownerList =
mDomainVerificationManager.getOwnersForDomain(host);
mSupportedLinkWrapperList.add(new SupportedLinkWrapper(getActivity(), host, ownerList));
index++;
// The cancel was clicked while progressing to collect data.
if (!mProgressAlertDialog.isShowing()) {
Log.w(TAG, "Exit the background thread!!!");
// clear buffer
mSupportedLinkWrapperList.clear();
break;
}
int progress = (int) (index * 100) / linksNo;
mHandle.post(() -> {
synchronized (mHandle) {
if (!mProgressAlertDialog.isShowing()) {
Log.w(TAG, "Exit the UI thread");
return;
}
mProgressAlertDialog.getProgressBar().setProgress(progress);
}
});
if (ownerList.size() == 0) {
SystemClock.sleep(PROGRESS_BAR_STEPPING_TIME);
}
}
IntentPickerUtils.logd("queryLinksInBackground : SupportedLinkWrapperList size="
+ mSupportedLinkWrapperList.size());
Collections.sort(mSupportedLinkWrapperList);
}
private void launchSupportedLinksDialogFragment() {
if (mSupportedLinkWrapperList.size() > 0) {
mViewModel.setSupportedLinkWrapperList(mSupportedLinkWrapperList);
final Bundle args = new Bundle();
args.putString(AppLaunchSettings.APP_PACKAGE_KEY, mPackage);
final SupportedLinksDialogFragment dialogFragment = new SupportedLinksDialogFragment();
dialogFragment.setArguments(args);
dialogFragment.showDialog(getActivity().getSupportFragmentManager());
}
}
/** Create a custom {@link AlertDialog} with a {@link ProgressBar}. */
static class ProgressAlertDialog extends AlertDialog {
private ProgressBar mProgressBar;
protected ProgressAlertDialog(@NonNull Context context) {
this(context, 0);
}
protected ProgressAlertDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
init(context);
}
private void init(Context context) {
final View view = LayoutInflater.from(context).inflate(
R.layout.app_launch_progress, /* root= */ null);
mProgressBar = view.findViewById(R.id.scan_links_progressbar);
mProgressBar.setProgress(0);
mProgressBar.setMax(100);
setView(view);
}
ProgressBar getProgressBar() {
return mProgressBar;
}
}
}