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:
		
							
								
								
									
										25
									
								
								res/layout/app_launch_progress.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								res/layout/app_launch_progress.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!-- 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.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<ProgressBar
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    style="@android:style/Widget.Material.ProgressBar.Horizontal"
 | 
			
		||||
    android:id="@+id/scan_links_progressbar"
 | 
			
		||||
    android:paddingTop="8dp"
 | 
			
		||||
    android:paddingStart="24dp"
 | 
			
		||||
    android:paddingEnd="24dp"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="wrap_content"/>
 | 
			
		||||
							
								
								
									
										49
									
								
								res/layout/app_launch_verified_links_title.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								res/layout/app_launch_verified_links_title.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!-- 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.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<LinearLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:orientation="vertical"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
    <LinearLayout
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:orientation="vertical"
 | 
			
		||||
        android:gravity="center"
 | 
			
		||||
        android:paddingStart="?android:attr/dialogPreferredPadding"
 | 
			
		||||
        android:paddingEnd="?android:attr/dialogPreferredPadding"
 | 
			
		||||
        android:paddingTop="@*android:dimen/dialog_padding_top_material">
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/dialog_title"
 | 
			
		||||
            android:singleLine="true"
 | 
			
		||||
            android:ellipsize="end"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:textAlignment="center"
 | 
			
		||||
            style="?android:attr/windowTitleStyle" />
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:paddingTop="12dp"
 | 
			
		||||
            android:id="@+id/dialog_message"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            style="@style/TextAppearance.DialogMessage" />
 | 
			
		||||
    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
</LinearLayout>
 | 
			
		||||
							
								
								
									
										28
									
								
								res/layout/preference_widget_info.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								res/layout/preference_widget_info.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!-- 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.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<ImageView
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:id="@+id/settings_button"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent"
 | 
			
		||||
    android:layout_gravity="center"
 | 
			
		||||
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
 | 
			
		||||
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
 | 
			
		||||
    android:background="?android:attr/selectableItemBackground"
 | 
			
		||||
    android:scaleType="center"
 | 
			
		||||
    android:src="@drawable/ic_info_outline_24"
 | 
			
		||||
    android:contentDescription="@string/settings_button" />
 | 
			
		||||
							
								
								
									
										31
									
								
								res/layout/supported_links_dialog_item.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								res/layout/supported_links_dialog_item.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!-- 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.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<CheckedTextView
 | 
			
		||||
     xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
     android:id="@android:id/text1"
 | 
			
		||||
     android:layout_width="match_parent"
 | 
			
		||||
     android:layout_height="wrap_content"
 | 
			
		||||
     android:minHeight="?android:attr/listPreferredItemHeightSmall"
 | 
			
		||||
     android:ellipsize="marquee"
 | 
			
		||||
     android:gravity="center_vertical"
 | 
			
		||||
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
 | 
			
		||||
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
 | 
			
		||||
     android:textAlignment="viewStart"
 | 
			
		||||
     android:textAppearance="?android:attr/textAppearanceListItemSmall"
 | 
			
		||||
     android:textColor="?android:attr/textColorAlertDialogListItem"
 | 
			
		||||
     android:drawableLeft="?android:attr/listChoiceIndicatorMultiple" />
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										25
									
								
								res/layout/verified_links_widget.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								res/layout/verified_links_widget.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!-- 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.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<LinearLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:layout_width="wrap_content"
 | 
			
		||||
    android:layout_height="match_parent"
 | 
			
		||||
    android:orientation="horizontal">
 | 
			
		||||
 | 
			
		||||
    <include layout="@layout/preference_widget_info"
 | 
			
		||||
             android:id="@+id/verified_links_widget" />
 | 
			
		||||
</LinearLayout>
 | 
			
		||||
@@ -16,31 +16,59 @@
 | 
			
		||||
 | 
			
		||||
<PreferenceScreen
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:settings="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
    android:title="@string/launch_by_default">
 | 
			
		||||
 | 
			
		||||
    <PreferenceCategory android:key="app_launch_domain_links"
 | 
			
		||||
                        android:title="@string/app_launch_domain_links_title">
 | 
			
		||||
    <com.android.settingslib.widget.MainSwitchPreference
 | 
			
		||||
        android:key="open_by_default_supported_links"
 | 
			
		||||
        android:title="@string/app_launch_open_domain_urls_title"/>
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
            android:key="app_link_state"
 | 
			
		||||
            android:summary="@string/summary_placeholder"
 | 
			
		||||
            android:title="@string/app_launch_open_domain_urls_title"/>
 | 
			
		||||
    <com.android.settingslib.widget.TopIntroPreference
 | 
			
		||||
        android:key="open_by_default_top_intro"
 | 
			
		||||
        android:title="@string/app_launch_top_intro_message"/>
 | 
			
		||||
 | 
			
		||||
        <com.android.settings.applications.AppDomainsPreference
 | 
			
		||||
            android:key="app_launch_supported_domain_urls"
 | 
			
		||||
            android:title="@string/app_launch_supported_domain_urls_title"
 | 
			
		||||
            android:dependency="app_link_state"
 | 
			
		||||
        />
 | 
			
		||||
    <PreferenceCategory
 | 
			
		||||
        android:layout="@layout/preference_category_no_label"
 | 
			
		||||
        android:key="open_by_default_main_category"
 | 
			
		||||
        settings:searchable="false">
 | 
			
		||||
 | 
			
		||||
        <PreferenceCategory
 | 
			
		||||
            android:title="@string/app_launch_links_category">
 | 
			
		||||
 | 
			
		||||
            <com.android.settings.applications.intentpicker.VerifiedLinksPreference
 | 
			
		||||
                android:key="open_by_default_verified_links"
 | 
			
		||||
                android:title="@string/summary_placeholder"
 | 
			
		||||
                android:order="-100"
 | 
			
		||||
                settings:searchable="false"/>
 | 
			
		||||
 | 
			
		||||
            <PreferenceCategory
 | 
			
		||||
                android:layout="@layout/preference_category_no_label"
 | 
			
		||||
                android:key="open_by_default_selected_links_category"
 | 
			
		||||
                android:order="100"
 | 
			
		||||
                settings:searchable="false"/>
 | 
			
		||||
 | 
			
		||||
            <Preference
 | 
			
		||||
                android:key="open_by_default_add_link"
 | 
			
		||||
                android:title="@string/app_launch_add_link"
 | 
			
		||||
                android:order="300"
 | 
			
		||||
                android:icon="@drawable/ic_add_24dp"/>
 | 
			
		||||
 | 
			
		||||
        </PreferenceCategory>
 | 
			
		||||
 | 
			
		||||
        <PreferenceCategory android:key="app_launch_other_defaults"
 | 
			
		||||
                            android:title="@string/app_launch_other_defaults_title">
 | 
			
		||||
 | 
			
		||||
            <com.android.settings.applications.ClearDefaultsPreference
 | 
			
		||||
                android:key="app_launch_clear_defaults"
 | 
			
		||||
                android:selectable="false"/>
 | 
			
		||||
 | 
			
		||||
        </PreferenceCategory>
 | 
			
		||||
 | 
			
		||||
        <com.android.settingslib.widget.FooterPreference
 | 
			
		||||
            android:key="open_by_default_footer"
 | 
			
		||||
            android:selectable="false"
 | 
			
		||||
            settings:allowDividerAbove="true"
 | 
			
		||||
            settings:searchable="false"/>
 | 
			
		||||
 | 
			
		||||
    </PreferenceCategory>
 | 
			
		||||
 | 
			
		||||
    <PreferenceCategory android:key="app_launch_other_defaults"
 | 
			
		||||
                        android:title="@string/app_launch_other_defaults_title">
 | 
			
		||||
 | 
			
		||||
        <com.android.settings.applications.ClearDefaultsPreference
 | 
			
		||||
            android:key="app_launch_clear_defaults"
 | 
			
		||||
            android:selectable="false"/>
 | 
			
		||||
 | 
			
		||||
    </PreferenceCategory>
 | 
			
		||||
 | 
			
		||||
</PreferenceScreen>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,152 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 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;
 | 
			
		||||
 | 
			
		||||
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
 | 
			
		||||
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
 | 
			
		||||
 | 
			
		||||
import android.app.settings.SettingsEnums;
 | 
			
		||||
import android.content.pm.ApplicationInfo;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.UserHandle;
 | 
			
		||||
import android.util.ArraySet;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.View.OnClickListener;
 | 
			
		||||
 | 
			
		||||
import androidx.appcompat.app.AlertDialog;
 | 
			
		||||
import androidx.preference.Preference;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
import com.android.settings.Utils;
 | 
			
		||||
import com.android.settings.core.SubSettingLauncher;
 | 
			
		||||
import com.android.settingslib.applications.AppUtils;
 | 
			
		||||
 | 
			
		||||
public class AppLaunchSettings extends AppInfoWithHeader implements OnClickListener,
 | 
			
		||||
        Preference.OnPreferenceChangeListener {
 | 
			
		||||
    private static final String TAG = "AppLaunchSettings";
 | 
			
		||||
    private static final String KEY_APP_LINK_STATE = "app_link_state";
 | 
			
		||||
    private static final String KEY_SUPPORTED_DOMAIN_URLS = "app_launch_supported_domain_urls";
 | 
			
		||||
    private static final String KEY_CLEAR_DEFAULTS = "app_launch_clear_defaults";
 | 
			
		||||
    private static final String FRAGMENT_OPEN_SUPPORTED_LINKS =
 | 
			
		||||
            "com.android.settings.applications.OpenSupportedLinks";
 | 
			
		||||
 | 
			
		||||
    private PackageManager mPm;
 | 
			
		||||
 | 
			
		||||
    private boolean mIsBrowser;
 | 
			
		||||
    private boolean mHasDomainUrls;
 | 
			
		||||
    private Preference mAppLinkState;
 | 
			
		||||
    private AppDomainsPreference mAppDomainUrls;
 | 
			
		||||
    private ClearDefaultsPreference mClearDefaultsPreference;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
        super.onCreate(savedInstanceState);
 | 
			
		||||
 | 
			
		||||
        addPreferencesFromResource(R.xml.installed_app_launch_settings);
 | 
			
		||||
        mAppDomainUrls = (AppDomainsPreference) findPreference(KEY_SUPPORTED_DOMAIN_URLS);
 | 
			
		||||
        mClearDefaultsPreference = (ClearDefaultsPreference) findPreference(KEY_CLEAR_DEFAULTS);
 | 
			
		||||
        mAppLinkState = findPreference(KEY_APP_LINK_STATE);
 | 
			
		||||
        mAppLinkState.setOnPreferenceClickListener(preference -> {
 | 
			
		||||
            final Bundle args = new Bundle();
 | 
			
		||||
            args.putString(ARG_PACKAGE_NAME, mPackageName);
 | 
			
		||||
            args.putInt(ARG_PACKAGE_UID, mUserId);
 | 
			
		||||
 | 
			
		||||
            new SubSettingLauncher(this.getContext())
 | 
			
		||||
                    .setDestination(FRAGMENT_OPEN_SUPPORTED_LINKS)
 | 
			
		||||
                    .setArguments(args)
 | 
			
		||||
                    .setSourceMetricsCategory(SettingsEnums.APPLICATIONS_APP_LAUNCH)
 | 
			
		||||
                    .setTitleRes(-1)
 | 
			
		||||
                    .launch();
 | 
			
		||||
            return true;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        mPm = getActivity().getPackageManager();
 | 
			
		||||
 | 
			
		||||
        mIsBrowser = AppUtils.isBrowserApp(this.getContext(), mPackageName, UserHandle.myUserId());
 | 
			
		||||
        mHasDomainUrls =
 | 
			
		||||
                (mAppEntry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
 | 
			
		||||
 | 
			
		||||
        if (!mIsBrowser) {
 | 
			
		||||
            CharSequence[] entries = getEntries(mPackageName);
 | 
			
		||||
            mAppDomainUrls.setTitles(entries);
 | 
			
		||||
            mAppDomainUrls.setValues(new int[entries.length]);
 | 
			
		||||
            mAppLinkState.setEnabled(mHasDomainUrls);
 | 
			
		||||
        } else {
 | 
			
		||||
            // Browsers don't show the app-link prefs
 | 
			
		||||
            mAppLinkState.setShouldDisableView(true);
 | 
			
		||||
            mAppLinkState.setEnabled(false);
 | 
			
		||||
            mAppDomainUrls.setShouldDisableView(true);
 | 
			
		||||
            mAppDomainUrls.setEnabled(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private int linkStateToResourceId(int state) {
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
 | 
			
		||||
                return R.string.app_link_open_always; // Always
 | 
			
		||||
            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER:
 | 
			
		||||
                return R.string.app_link_open_never; // Never
 | 
			
		||||
            default:
 | 
			
		||||
                return R.string.app_link_open_ask; // Ask
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private CharSequence[] getEntries(String packageName) {
 | 
			
		||||
        ArraySet<String> result = Utils.getHandledDomains(mPm, packageName);
 | 
			
		||||
        return result.toArray(new CharSequence[result.size()]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void setAppLinkStateSummary() {
 | 
			
		||||
        final int state = mPm.getIntentVerificationStatusAsUser(mPackageName,
 | 
			
		||||
                UserHandle.myUserId());
 | 
			
		||||
        mAppLinkState.setSummary(linkStateToResourceId(state));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected boolean refreshUi() {
 | 
			
		||||
        if (mHasDomainUrls) {
 | 
			
		||||
            //Update the summary after return from the OpenSupportedLinks
 | 
			
		||||
            setAppLinkStateSummary();
 | 
			
		||||
        }
 | 
			
		||||
        mClearDefaultsPreference.setPackageName(mPackageName);
 | 
			
		||||
        mClearDefaultsPreference.setAppEntry(mAppEntry);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected AlertDialog createDialog(int id, int errorCode) {
 | 
			
		||||
        // No dialogs for preferred launch settings.
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onClick(View v) {
 | 
			
		||||
        // Nothing to do
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onPreferenceChange(Preference preference, Object newValue) {
 | 
			
		||||
        // actual updates are handled by the app link dropdown callback
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getMetricsCategory() {
 | 
			
		||||
        return SettingsEnums.APPLICATIONS_APP_LAUNCH;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -117,7 +117,7 @@ public class ClearDefaultsPreference extends Preference {
 | 
			
		||||
                if (mUsbManager != null) {
 | 
			
		||||
                    final int userId = UserHandle.myUserId();
 | 
			
		||||
                    mPm.clearPackagePreferredActivities(mPackageName);
 | 
			
		||||
                    if (isDefaultBrowser(mPackageName)) {
 | 
			
		||||
                    if (AppUtils.isDefaultBrowser(getContext(), mPackageName)) {
 | 
			
		||||
                        mPm.setDefaultBrowserPackageNameAsUser(null, userId);
 | 
			
		||||
                    }
 | 
			
		||||
                    try {
 | 
			
		||||
@@ -141,7 +141,7 @@ public class ClearDefaultsPreference extends Preference {
 | 
			
		||||
 | 
			
		||||
        TextView autoLaunchView = (TextView) view.findViewById(R.id.auto_launch);
 | 
			
		||||
        boolean autoLaunchEnabled = AppUtils.hasPreferredActivities(mPm, mPackageName)
 | 
			
		||||
                || isDefaultBrowser(mPackageName)
 | 
			
		||||
                || AppUtils.isDefaultBrowser(getContext(), mPackageName)
 | 
			
		||||
                || AppUtils.hasUsbDefaults(mUsbManager, mPackageName);
 | 
			
		||||
        if (!autoLaunchEnabled && !hasBindAppWidgetPermission) {
 | 
			
		||||
            resetLaunchDefaultsUi(autoLaunchView);
 | 
			
		||||
@@ -185,11 +185,6 @@ public class ClearDefaultsPreference extends Preference {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isDefaultBrowser(String packageName) {
 | 
			
		||||
        final String defaultBrowser = mPm.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId());
 | 
			
		||||
        return packageName.equals(defaultBrowser);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void resetLaunchDefaultsUi(TextView autoLaunchView) {
 | 
			
		||||
        autoLaunchView.setText(R.string.auto_launch_disable_text);
 | 
			
		||||
        // Disable clear activities button
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ package com.android.settings.applications;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.SettingsActivity;
 | 
			
		||||
import com.android.settings.applications.intentpicker.AppLaunchSettings;
 | 
			
		||||
 | 
			
		||||
public class InstalledAppOpenByDefaultActivity extends SettingsActivity {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ import androidx.preference.Preference;
 | 
			
		||||
import androidx.preference.PreferenceScreen;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.SettingsPreferenceFragment;
 | 
			
		||||
import com.android.settings.applications.AppLaunchSettings;
 | 
			
		||||
import com.android.settings.applications.intentpicker.AppLaunchSettings;
 | 
			
		||||
import com.android.settingslib.applications.AppUtils;
 | 
			
		||||
import com.android.settingslib.applications.ApplicationsState;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,404 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 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 static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_SELECTED;
 | 
			
		||||
import static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_VERIFIED;
 | 
			
		||||
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.app.settings.SettingsEnums;
 | 
			
		||||
import android.appwidget.AppWidgetManager;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.content.pm.verify.domain.DomainVerificationManager;
 | 
			
		||||
import android.content.pm.verify.domain.DomainVerificationUserState;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.util.ArraySet;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.widget.Switch;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.VisibleForTesting;
 | 
			
		||||
import androidx.appcompat.app.AlertDialog;
 | 
			
		||||
import androidx.preference.Preference;
 | 
			
		||||
import androidx.preference.PreferenceCategory;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
import com.android.settings.Utils;
 | 
			
		||||
import com.android.settings.applications.AppInfoBase;
 | 
			
		||||
import com.android.settings.applications.ClearDefaultsPreference;
 | 
			
		||||
import com.android.settings.utils.AnnotationSpan;
 | 
			
		||||
import com.android.settings.widget.EntityHeaderController;
 | 
			
		||||
import com.android.settingslib.applications.AppUtils;
 | 
			
		||||
import com.android.settingslib.widget.FooterPreference;
 | 
			
		||||
import com.android.settingslib.widget.MainSwitchPreference;
 | 
			
		||||
import com.android.settingslib.widget.OnMainSwitchChangeListener;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
/** The page of the Open by default */
 | 
			
		||||
public class AppLaunchSettings extends AppInfoBase implements
 | 
			
		||||
        Preference.OnPreferenceChangeListener, OnMainSwitchChangeListener {
 | 
			
		||||
    private static final String TAG = "AppLaunchSettings";
 | 
			
		||||
    // Preference keys
 | 
			
		||||
    private static final String MAIN_SWITCH_PREF_KEY = "open_by_default_supported_links";
 | 
			
		||||
    private static final String VERIFIED_LINKS_PREF_KEY = "open_by_default_verified_links";
 | 
			
		||||
    private static final String ADD_LINK_PREF_KEY = "open_by_default_add_link";
 | 
			
		||||
    private static final String CLEAR_DEFAULTS_PREF_KEY = "app_launch_clear_defaults";
 | 
			
		||||
    private static final String FOOTER_PREF_KEY = "open_by_default_footer";
 | 
			
		||||
 | 
			
		||||
    private static final String MAIN_PREF_CATEGORY_KEY = "open_by_default_main_category";
 | 
			
		||||
    private static final String SELECTED_LINKS_CATEGORY_KEY =
 | 
			
		||||
            "open_by_default_selected_links_category";
 | 
			
		||||
    private static final String OTHER_DETAILS_PREF_CATEGORY_KEY = "app_launch_other_defaults";
 | 
			
		||||
 | 
			
		||||
    // Url and Uri
 | 
			
		||||
    private static final String ANNOTATION_URL = "url";
 | 
			
		||||
    private static final String LEARN_MORE_URI =
 | 
			
		||||
            "https://developer.android.com/training/app-links/verify-site-associations";
 | 
			
		||||
 | 
			
		||||
    // Dialogs id
 | 
			
		||||
    private static final int DLG_VERIFIED_LINKS = DLG_BASE + 1;
 | 
			
		||||
 | 
			
		||||
    // Arguments key
 | 
			
		||||
    public static final String APP_PACKAGE_KEY = "app_package";
 | 
			
		||||
 | 
			
		||||
    private ClearDefaultsPreference mClearDefaultsPreference;
 | 
			
		||||
    private MainSwitchPreference mMainSwitchPreference;
 | 
			
		||||
    private PreferenceCategory mMainPreferenceCategory;
 | 
			
		||||
    private PreferenceCategory mSelectedLinksPreferenceCategory;
 | 
			
		||||
    private PreferenceCategory mOtherDefaultsPreferenceCategory;
 | 
			
		||||
 | 
			
		||||
    private boolean mActivityCreated;
 | 
			
		||||
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    Context mContext;
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    DomainVerificationManager mDomainVerificationManager;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onAttach(Context context) {
 | 
			
		||||
        super.onAttach(context);
 | 
			
		||||
        mContext = context;
 | 
			
		||||
        mActivityCreated = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
        super.onCreate(savedInstanceState);
 | 
			
		||||
        addPreferencesFromResource(R.xml.installed_app_launch_settings);
 | 
			
		||||
        mDomainVerificationManager = mContext.getSystemService(DomainVerificationManager.class);
 | 
			
		||||
        initUIComponents();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onViewCreated(View view, Bundle savedInstanceState) {
 | 
			
		||||
        super.onViewCreated(view, savedInstanceState);
 | 
			
		||||
        createHeaderPreference();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getMetricsCategory() {
 | 
			
		||||
        return SettingsEnums.APPLICATIONS_APP_LAUNCH;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected AlertDialog createDialog(int id, int errorCode) {
 | 
			
		||||
        if (id == DLG_VERIFIED_LINKS) {
 | 
			
		||||
            return createVerifiedLinksDialog();
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected boolean refreshUi() {
 | 
			
		||||
        mClearDefaultsPreference.setPackageName(mPackageName);
 | 
			
		||||
        mClearDefaultsPreference.setAppEntry(mAppEntry);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onPreferenceChange(Preference preference, Object newValue) {
 | 
			
		||||
        final boolean isChecked = (boolean) newValue;
 | 
			
		||||
        IntentPickerUtils.logd(
 | 
			
		||||
                "onPreferenceChange: " + preference.getTitle() + " isChecked: " + isChecked);
 | 
			
		||||
        if ((preference instanceof LeftSideCheckBoxPreference) && !isChecked) {
 | 
			
		||||
            final Set<String> domainSet = new ArraySet<>();
 | 
			
		||||
            domainSet.add(preference.getTitle().toString());
 | 
			
		||||
            removePreference(preference.getKey());
 | 
			
		||||
            final DomainVerificationUserState userState =
 | 
			
		||||
                    IntentPickerUtils.getDomainVerificationUserState(mDomainVerificationManager,
 | 
			
		||||
                            mPackageName);
 | 
			
		||||
            if (userState == null) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            setDomainVerificationUserSelection(userState.getIdentifier(), domainSet, /* enabled= */
 | 
			
		||||
                    false);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onSwitchChanged(Switch switchView, boolean isChecked) {
 | 
			
		||||
        IntentPickerUtils.logd("onSwitchChanged: isChecked=" + isChecked);
 | 
			
		||||
        if (mMainSwitchPreference != null) { //mMainSwitchPreference synced with Switch
 | 
			
		||||
            mMainSwitchPreference.setChecked(isChecked);
 | 
			
		||||
        }
 | 
			
		||||
        if (mMainPreferenceCategory != null) {
 | 
			
		||||
            mMainPreferenceCategory.setVisible(isChecked);
 | 
			
		||||
        }
 | 
			
		||||
        if (mDomainVerificationManager != null) {
 | 
			
		||||
            try {
 | 
			
		||||
                mDomainVerificationManager.setDomainVerificationLinkHandlingAllowed(mPackageName,
 | 
			
		||||
                        isChecked);
 | 
			
		||||
            } catch (PackageManager.NameNotFoundException e) {
 | 
			
		||||
                Log.w(TAG, "onSwitchChanged: " + e.getMessage());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void createHeaderPreference() {
 | 
			
		||||
        if (mActivityCreated) {
 | 
			
		||||
            Log.w(TAG, "onParentActivityCreated: ignoring duplicate call.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        mActivityCreated = true;
 | 
			
		||||
        if (mPackageInfo == null) {
 | 
			
		||||
            Log.w(TAG, "onParentActivityCreated: PakcageInfo is null.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        final Activity activity = getActivity();
 | 
			
		||||
        final Preference pref = EntityHeaderController
 | 
			
		||||
                .newInstance(activity, this, null /* header */)
 | 
			
		||||
                .setRecyclerView(getListView(), getSettingsLifecycle())
 | 
			
		||||
                .setIcon(Utils.getBadgedIcon(mContext, mPackageInfo.applicationInfo))
 | 
			
		||||
                .setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
 | 
			
		||||
                .setSummary("" /* summary */)  // no version number
 | 
			
		||||
                .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
 | 
			
		||||
                .setPackageName(mPackageName)
 | 
			
		||||
                .setUid(mPackageInfo.applicationInfo.uid)
 | 
			
		||||
                .setHasAppInfoLink(true)
 | 
			
		||||
                .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
 | 
			
		||||
                        EntityHeaderController.ActionType.ACTION_NONE)
 | 
			
		||||
                .done(activity, getPrefContext());
 | 
			
		||||
        getPreferenceScreen().addPreference(pref);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void initUIComponents() {
 | 
			
		||||
        initMainSwitchAndCategories();
 | 
			
		||||
        if (canUpdateMainSwitchAndCategories()) {
 | 
			
		||||
            initVerifiedLinksPreference();
 | 
			
		||||
            addSelectedLinksPreference();
 | 
			
		||||
            initAddLinkPreference();
 | 
			
		||||
            initFooter();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void initMainSwitchAndCategories() {
 | 
			
		||||
        mMainSwitchPreference = (MainSwitchPreference) findPreference(MAIN_SWITCH_PREF_KEY);
 | 
			
		||||
        mMainPreferenceCategory = findPreference(MAIN_PREF_CATEGORY_KEY);
 | 
			
		||||
        mSelectedLinksPreferenceCategory = findPreference(SELECTED_LINKS_CATEGORY_KEY);
 | 
			
		||||
        // Initialize the "Other Default Category" section
 | 
			
		||||
        initOtherDefaultsSection();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean canUpdateMainSwitchAndCategories() {
 | 
			
		||||
        final DomainVerificationUserState userState =
 | 
			
		||||
                IntentPickerUtils.getDomainVerificationUserState(mDomainVerificationManager,
 | 
			
		||||
                        mPackageName);
 | 
			
		||||
        if (userState == null) {
 | 
			
		||||
            disabledPreference();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        IntentPickerUtils.logd("isLinkHandlingAllowed() : " + userState.isLinkHandlingAllowed());
 | 
			
		||||
        mMainSwitchPreference.updateStatus(userState.isLinkHandlingAllowed());
 | 
			
		||||
        mMainSwitchPreference.addOnSwitchChangeListener(this);
 | 
			
		||||
        mMainPreferenceCategory.setVisible(userState.isLinkHandlingAllowed());
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Initialize verified links preference */
 | 
			
		||||
    private void initVerifiedLinksPreference() {
 | 
			
		||||
        final VerifiedLinksPreference verifiedLinksPreference =
 | 
			
		||||
                (VerifiedLinksPreference) mMainPreferenceCategory.findPreference(
 | 
			
		||||
                        VERIFIED_LINKS_PREF_KEY);
 | 
			
		||||
        verifiedLinksPreference.setWidgetFrameClickListener(l -> {
 | 
			
		||||
            showVerifiedLinksDialog();
 | 
			
		||||
        });
 | 
			
		||||
        final int verifiedLinksNo = getLinksNumber(DOMAIN_STATE_VERIFIED);
 | 
			
		||||
        verifiedLinksPreference.setTitle(getVerifiedLinksTitle(verifiedLinksNo));
 | 
			
		||||
        verifiedLinksPreference.setCheckBoxVisible(verifiedLinksNo > 0);
 | 
			
		||||
        verifiedLinksPreference.setEnabled(verifiedLinksNo > 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void showVerifiedLinksDialog() {
 | 
			
		||||
        final int linksNo = getLinksNumber(DOMAIN_STATE_VERIFIED);
 | 
			
		||||
        if (linksNo == 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        showDialogInner(DLG_VERIFIED_LINKS, /* moveErrorCode= */ 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private AlertDialog createVerifiedLinksDialog() {
 | 
			
		||||
        final int linksNo = getLinksNumber(DOMAIN_STATE_VERIFIED);
 | 
			
		||||
 | 
			
		||||
        final View titleView = LayoutInflater.from(mContext).inflate(
 | 
			
		||||
                R.layout.app_launch_verified_links_title, /* root= */ null);
 | 
			
		||||
        ((TextView) titleView.findViewById(R.id.dialog_title)).setText(
 | 
			
		||||
                getVerifiedLinksTitle(linksNo));
 | 
			
		||||
        ((TextView) titleView.findViewById(R.id.dialog_message)).setText(
 | 
			
		||||
                getVerifiedLinksMessage(linksNo));
 | 
			
		||||
 | 
			
		||||
        final List<String> verifiedLinksList = IntentPickerUtils.getLinksList(
 | 
			
		||||
                mDomainVerificationManager, mPackageName, DOMAIN_STATE_VERIFIED);
 | 
			
		||||
        return new AlertDialog.Builder(mContext)
 | 
			
		||||
                .setCustomTitle(titleView)
 | 
			
		||||
                .setCancelable(true)
 | 
			
		||||
                .setItems(verifiedLinksList.toArray(new String[0]), /* listener= */ null)
 | 
			
		||||
                .setPositiveButton(R.string.app_launch_dialog_ok, /* listener= */ null)
 | 
			
		||||
                .create();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    String getVerifiedLinksTitle(int linksNo) {
 | 
			
		||||
        return getResources().getQuantityString(
 | 
			
		||||
                R.plurals.app_launch_verified_links_title, linksNo, linksNo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getVerifiedLinksMessage(int linksNo) {
 | 
			
		||||
        return getResources().getQuantityString(
 | 
			
		||||
                R.plurals.app_launch_verified_links_message, linksNo, linksNo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Add selected links items */
 | 
			
		||||
    public void addSelectedLinksPreference() {
 | 
			
		||||
        if (getLinksNumber(DOMAIN_STATE_SELECTED) == 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        mSelectedLinksPreferenceCategory.removeAll();
 | 
			
		||||
        final List<String> selectedLinks = IntentPickerUtils.getLinksList(
 | 
			
		||||
                mDomainVerificationManager, mPackageName, DOMAIN_STATE_SELECTED);
 | 
			
		||||
        for (String host : selectedLinks) {
 | 
			
		||||
            generateCheckBoxPreference(mSelectedLinksPreferenceCategory, host);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Initialize add link preference */
 | 
			
		||||
    private void initAddLinkPreference() {
 | 
			
		||||
        final Preference addLinkPreference = findPreference(ADD_LINK_PREF_KEY);
 | 
			
		||||
        if (addLinkPreference != null) {
 | 
			
		||||
            addLinkPreference.setEnabled(getLinksNumber(DOMAIN_STATE_NONE) > 0);
 | 
			
		||||
            addLinkPreference.setOnPreferenceClickListener(preference -> {
 | 
			
		||||
                final int stateNoneLinksNo = getLinksNumber(DOMAIN_STATE_NONE);
 | 
			
		||||
                IntentPickerUtils.logd("The number of the state none links: " + stateNoneLinksNo);
 | 
			
		||||
                if (stateNoneLinksNo > 0) {
 | 
			
		||||
                    showProgressDialogFragment();
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void showProgressDialogFragment() {
 | 
			
		||||
        final Bundle args = new Bundle();
 | 
			
		||||
        args.putString(APP_PACKAGE_KEY, mPackageName);
 | 
			
		||||
        final ProgressDialogFragment dialogFragment = new ProgressDialogFragment();
 | 
			
		||||
        dialogFragment.setArguments(args);
 | 
			
		||||
        dialogFragment.showDialog(getActivity().getSupportFragmentManager());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void disabledPreference() {
 | 
			
		||||
        mMainSwitchPreference.updateStatus(false);
 | 
			
		||||
        mMainSwitchPreference.setSelectable(false);
 | 
			
		||||
        mMainSwitchPreference.setEnabled(false);
 | 
			
		||||
        mMainPreferenceCategory.setVisible(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Init OTHER DEFAULTS category */
 | 
			
		||||
    private void initOtherDefaultsSection() {
 | 
			
		||||
        mOtherDefaultsPreferenceCategory = findPreference(OTHER_DETAILS_PREF_CATEGORY_KEY);
 | 
			
		||||
        mOtherDefaultsPreferenceCategory.setVisible(isClearDefaultsEnabled());
 | 
			
		||||
        mClearDefaultsPreference = (ClearDefaultsPreference) findPreference(
 | 
			
		||||
                CLEAR_DEFAULTS_PREF_KEY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void initFooter() {
 | 
			
		||||
        // learn more
 | 
			
		||||
        final AnnotationSpan.LinkInfo linkInfo =
 | 
			
		||||
                new AnnotationSpan.LinkInfo(ANNOTATION_URL, v -> {
 | 
			
		||||
                    final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(LEARN_MORE_URI));
 | 
			
		||||
                    mContext.startActivity(intent);
 | 
			
		||||
                });
 | 
			
		||||
        final CharSequence footerText = mContext.getText(R.string.app_launch_footer);
 | 
			
		||||
        final FooterPreference footerPreference = (FooterPreference) findPreference(
 | 
			
		||||
                FOOTER_PREF_KEY);
 | 
			
		||||
        footerPreference.setTitle(AnnotationSpan.linkify(footerText, linkInfo));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isClearDefaultsEnabled() {
 | 
			
		||||
        final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
 | 
			
		||||
        final boolean hasBindAppWidgetPermission =
 | 
			
		||||
                appWidgetManager.hasBindAppWidgetPermission(mAppEntry.info.packageName);
 | 
			
		||||
 | 
			
		||||
        final boolean isAutoLaunchEnabled = AppUtils.hasPreferredActivities(mPm, mPackageName)
 | 
			
		||||
                || AppUtils.isDefaultBrowser(mContext, mPackageName)
 | 
			
		||||
                || AppUtils.hasUsbDefaults(mUsbManager, mPackageName);
 | 
			
		||||
 | 
			
		||||
        IntentPickerUtils.logd("isClearDefaultsEnabled hasBindAppWidgetPermission : "
 | 
			
		||||
                + hasBindAppWidgetPermission);
 | 
			
		||||
        IntentPickerUtils.logd(
 | 
			
		||||
                "isClearDefaultsEnabled isAutoLaunchEnabled : " + isAutoLaunchEnabled);
 | 
			
		||||
        return (isAutoLaunchEnabled || hasBindAppWidgetPermission);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void setDomainVerificationUserSelection(UUID identifier, Set<String> domainSet,
 | 
			
		||||
            boolean isEnabled) {
 | 
			
		||||
        try {
 | 
			
		||||
            mDomainVerificationManager.setDomainVerificationUserSelection(identifier, domainSet,
 | 
			
		||||
                    isEnabled);
 | 
			
		||||
        } catch (PackageManager.NameNotFoundException e) {
 | 
			
		||||
            Log.w(TAG, "addSelectedItems : " + e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void generateCheckBoxPreference(PreferenceCategory parent, String title) {
 | 
			
		||||
        final LeftSideCheckBoxPreference checkBoxPreference = new LeftSideCheckBoxPreference(
 | 
			
		||||
                parent.getContext(), /* isChecked= */ true);
 | 
			
		||||
        checkBoxPreference.setTitle(title);
 | 
			
		||||
        checkBoxPreference.setOnPreferenceChangeListener(this);
 | 
			
		||||
        checkBoxPreference.setKey(UUID.randomUUID().toString());
 | 
			
		||||
        parent.addPreference(checkBoxPreference);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** get the number of the specify links */
 | 
			
		||||
    private int getLinksNumber(@DomainVerificationUserState.DomainState int state) {
 | 
			
		||||
        final List<String> linkList = IntentPickerUtils.getLinksList(
 | 
			
		||||
                mDomainVerificationManager, mPackageName, state);
 | 
			
		||||
        if (linkList == null) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        return linkList.size();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,98 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 android.content.pm.PackageManager;
 | 
			
		||||
import android.content.pm.verify.domain.DomainVerificationManager;
 | 
			
		||||
import android.content.pm.verify.domain.DomainVerificationUserState;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.text.Layout;
 | 
			
		||||
import android.text.SpannableString;
 | 
			
		||||
import android.text.style.AlignmentSpan;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/** The common APIs for intent picker */
 | 
			
		||||
public class IntentPickerUtils {
 | 
			
		||||
    private static final String TAG = "IntentPickerUtils";
 | 
			
		||||
    private static final boolean DEBUG = Build.IS_DEBUGGABLE;
 | 
			
		||||
 | 
			
		||||
    private IntentPickerUtils() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the centralized title.
 | 
			
		||||
     *
 | 
			
		||||
     * @param title The title of the dialog box.
 | 
			
		||||
     * @return The spannable string with centralized title.
 | 
			
		||||
     */
 | 
			
		||||
    public static SpannableString getCentralizedDialogTitle(String title) {
 | 
			
		||||
        final SpannableString dialogTitle = new SpannableString(title);
 | 
			
		||||
        dialogTitle.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER), /* start= */
 | 
			
		||||
                0, title.length(), /* flags= */ 0);
 | 
			
		||||
        return dialogTitle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the {@link DomainVerificationUserState} for specific application.
 | 
			
		||||
     *
 | 
			
		||||
     * @param manager The {@link DomainVerificationManager}.
 | 
			
		||||
     * @param pkgName The package name of the target application.
 | 
			
		||||
     */
 | 
			
		||||
    public static DomainVerificationUserState getDomainVerificationUserState(
 | 
			
		||||
            DomainVerificationManager manager, String pkgName) {
 | 
			
		||||
        try {
 | 
			
		||||
            final DomainVerificationUserState domainVerificationUserState =
 | 
			
		||||
                    manager.getDomainVerificationUserState(pkgName);
 | 
			
		||||
            return domainVerificationUserState;
 | 
			
		||||
        } catch (PackageManager.NameNotFoundException e) {
 | 
			
		||||
            Log.w(TAG, e.getMessage());
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the links list by {@link DomainVerificationUserState.DomainState}
 | 
			
		||||
     *
 | 
			
		||||
     * @param manager The {@link DomainVerificationManager}.
 | 
			
		||||
     * @param pkgName The package name of the target application.
 | 
			
		||||
     * @param state   The user state you want to query.
 | 
			
		||||
     * @return A links list.
 | 
			
		||||
     */
 | 
			
		||||
    public static List<String> getLinksList(DomainVerificationManager manager, String pkgName,
 | 
			
		||||
            @DomainVerificationUserState.DomainState int state) {
 | 
			
		||||
        final DomainVerificationUserState userStage = getDomainVerificationUserState(manager,
 | 
			
		||||
                pkgName);
 | 
			
		||||
        if (userStage == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        return userStage.getHostToStateMap()
 | 
			
		||||
                .entrySet()
 | 
			
		||||
                .stream()
 | 
			
		||||
                .filter(it -> it.getValue() == state)
 | 
			
		||||
                .map(it -> it.getKey())
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Logs the message in debug ROM. */
 | 
			
		||||
    public static void logd(String msg) {
 | 
			
		||||
        if (DEBUG) {
 | 
			
		||||
            Log.d(TAG, msg);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,74 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 android.content.Context;
 | 
			
		||||
import android.util.AttributeSet;
 | 
			
		||||
import android.widget.CheckBox;
 | 
			
		||||
 | 
			
		||||
import androidx.preference.PreferenceViewHolder;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
import com.android.settingslib.widget.TwoTargetPreference;
 | 
			
		||||
 | 
			
		||||
/** This preference has a check box in the left side. */
 | 
			
		||||
public class LeftSideCheckBoxPreference extends TwoTargetPreference {
 | 
			
		||||
    private boolean mChecked;
 | 
			
		||||
    private CheckBox mCheckBox;
 | 
			
		||||
 | 
			
		||||
    public LeftSideCheckBoxPreference(Context context, AttributeSet attrs,
 | 
			
		||||
            int defStyleAttr, int defStyleRes) {
 | 
			
		||||
        super(context, attrs, defStyleAttr, defStyleRes);
 | 
			
		||||
        setLayoutResource(R.layout.preference_checkable_two_target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public LeftSideCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
 | 
			
		||||
        this(context, attrs, defStyleAttr, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public LeftSideCheckBoxPreference(Context context, AttributeSet attrs) {
 | 
			
		||||
        this(context, attrs, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public LeftSideCheckBoxPreference(Context context) {
 | 
			
		||||
        this(context, /* attrs= */ null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public LeftSideCheckBoxPreference(Context context, boolean isChecked) {
 | 
			
		||||
        super(context);
 | 
			
		||||
        mChecked = isChecked;
 | 
			
		||||
        setLayoutResource(R.layout.preference_checkable_two_target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onBindViewHolder(PreferenceViewHolder view) {
 | 
			
		||||
        super.onBindViewHolder(view);
 | 
			
		||||
        mCheckBox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox);
 | 
			
		||||
        if (mCheckBox != null) {
 | 
			
		||||
            mCheckBox.setChecked(mChecked);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onClick() {
 | 
			
		||||
        if (mCheckBox != null) {
 | 
			
		||||
            mChecked = !mChecked;
 | 
			
		||||
            mCheckBox.setChecked(mChecked);
 | 
			
		||||
            callChangeListener(mChecked);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 android.app.Application;
 | 
			
		||||
 | 
			
		||||
import androidx.lifecycle.AndroidViewModel;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This {@link AndroidViewModel} provides supported link wrapper data
 | 
			
		||||
 * between multiple fragments.
 | 
			
		||||
 */
 | 
			
		||||
public class SupportedLinkViewModel extends AndroidViewModel {
 | 
			
		||||
    private List<SupportedLinkWrapper> mSupportedLinkWrapperList;
 | 
			
		||||
 | 
			
		||||
    public SupportedLinkViewModel(Application application) {
 | 
			
		||||
        super(application);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Clear the list buffer of the {@link SupportedLinkWrapper}. */
 | 
			
		||||
    public void clearSupportedLinkWrapperList() {
 | 
			
		||||
        mSupportedLinkWrapperList = new ArrayList<>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Set the list buffer of the {@link SupportedLinkWrapper}. */
 | 
			
		||||
    public void setSupportedLinkWrapperList(List<SupportedLinkWrapper> wrapperList) {
 | 
			
		||||
        mSupportedLinkWrapperList = wrapperList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Get the list buffer of the {@link SupportedLinkWrapper}. */
 | 
			
		||||
    public List<SupportedLinkWrapper> getSupportedLinkWrapperList() {
 | 
			
		||||
        return mSupportedLinkWrapperList;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,124 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 android.content.Context;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.content.pm.verify.domain.DomainOwner;
 | 
			
		||||
import android.text.TextUtils;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  A buffer of the supported link data. This {@link SupportedLinkWrapper} wraps the host, enabled
 | 
			
		||||
 *  and a list of {@link DomainOwner}.
 | 
			
		||||
 */
 | 
			
		||||
public class SupportedLinkWrapper implements Comparable {
 | 
			
		||||
    private static final String TAG = "SupportedLinkWrapper";
 | 
			
		||||
 | 
			
		||||
    private String mHost;
 | 
			
		||||
    private List<DomainOwner> mOwnerList;
 | 
			
		||||
    private boolean mIsEnabled;
 | 
			
		||||
    private String mLastOwnerName;
 | 
			
		||||
    private boolean mIsChecked;
 | 
			
		||||
 | 
			
		||||
    public SupportedLinkWrapper(Context context, String host, List<DomainOwner> ownerList) {
 | 
			
		||||
        mHost = host;
 | 
			
		||||
        mOwnerList = ownerList;
 | 
			
		||||
        mIsEnabled = true;
 | 
			
		||||
        mLastOwnerName = "";
 | 
			
		||||
        mIsChecked = false;
 | 
			
		||||
        init(context);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void init(Context context) {
 | 
			
		||||
        if (mOwnerList.size() > 0) {
 | 
			
		||||
            final long nonOverirideableNo = mOwnerList.stream()
 | 
			
		||||
                    .filter(it -> !it.isOverrideable())
 | 
			
		||||
                    .count();
 | 
			
		||||
            mIsEnabled = (nonOverirideableNo == 0L);
 | 
			
		||||
            if (nonOverirideableNo > 0L) {
 | 
			
		||||
                mLastOwnerName = getLastPackageLabel(context, false);
 | 
			
		||||
            } else {
 | 
			
		||||
                mLastOwnerName = getLastPackageLabel(context, true);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getLastPackageLabel(Context context, boolean isOverrideable) {
 | 
			
		||||
        final List<String> labelList = mOwnerList.stream()
 | 
			
		||||
                .filter(it -> it.isOverrideable() == isOverrideable)
 | 
			
		||||
                .map(it -> getLabel(context, it.getPackageName()))
 | 
			
		||||
                .filter(label -> label != null)
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
        return labelList.get(labelList.size() - 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getLabel(Context context, String pkg) {
 | 
			
		||||
        try {
 | 
			
		||||
            final PackageManager pm = context.getPackageManager();
 | 
			
		||||
            return pm.getApplicationInfo(pkg, /* flags= */ 0).loadLabel(pm).toString();
 | 
			
		||||
        } catch (PackageManager.NameNotFoundException e) {
 | 
			
		||||
            Log.w(TAG, "getLabel error : " + e.getMessage());
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Returns the enabled/disabled value for list item. */
 | 
			
		||||
    public boolean isEnabled() {
 | 
			
		||||
        return mIsEnabled;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Returns the display format of list item in the Supported Links dialog */
 | 
			
		||||
    public String getDisplayTitle(Context context) {
 | 
			
		||||
        if (TextUtils.isEmpty(mLastOwnerName) || context == null) {
 | 
			
		||||
            return mHost;
 | 
			
		||||
        }
 | 
			
		||||
        return mHost + System.lineSeparator() + context.getString(
 | 
			
		||||
                R.string.app_launch_supported_links_subtext, mLastOwnerName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Returns the host name. */
 | 
			
		||||
    public String getHost() {
 | 
			
		||||
        return mHost;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Returns the checked value for list item. */
 | 
			
		||||
    public boolean isChecked() {
 | 
			
		||||
        return mIsChecked;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Set the checked value. */
 | 
			
		||||
    public void setChecked(boolean isChecked) {
 | 
			
		||||
        mIsChecked = isChecked;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int compareTo(Object o) {
 | 
			
		||||
        final SupportedLinkWrapper that = (SupportedLinkWrapper) o;
 | 
			
		||||
        if (this.mIsEnabled != that.mIsEnabled) {
 | 
			
		||||
            return this.mIsEnabled ? -1 : 1;
 | 
			
		||||
        }
 | 
			
		||||
        if (TextUtils.isEmpty(this.mLastOwnerName) != TextUtils.isEmpty(that.mLastOwnerName)) {
 | 
			
		||||
            return TextUtils.isEmpty(this.mLastOwnerName) ? -1 : 1;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,74 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 android.content.Context;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
import android.widget.BaseAdapter;
 | 
			
		||||
import android.widget.CheckedTextView;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/** This adapter is for supported links dialog. */
 | 
			
		||||
public class SupportedLinksAdapter extends BaseAdapter {
 | 
			
		||||
    private final Context mContext;
 | 
			
		||||
    private final List<SupportedLinkWrapper> mWrapperList;
 | 
			
		||||
 | 
			
		||||
    public SupportedLinksAdapter(Context context, List<SupportedLinkWrapper> list) {
 | 
			
		||||
        mContext = context;
 | 
			
		||||
        mWrapperList = list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getCount() {
 | 
			
		||||
        return mWrapperList.size();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object getItem(int position) {
 | 
			
		||||
        if (position < mWrapperList.size()) {
 | 
			
		||||
            return mWrapperList.get(position);
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getItemId(int position) {
 | 
			
		||||
        return position;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public View getView(int position, View convertView, ViewGroup parent) {
 | 
			
		||||
        if (convertView == null) {
 | 
			
		||||
            convertView = LayoutInflater.from(mContext).inflate(
 | 
			
		||||
                    R.layout.supported_links_dialog_item, /* root= */ null);
 | 
			
		||||
        }
 | 
			
		||||
        final CheckedTextView textView = convertView.findViewById(android.R.id.text1);
 | 
			
		||||
        textView.setText(mWrapperList.get(position).getDisplayTitle(mContext));
 | 
			
		||||
        textView.setEnabled(mWrapperList.get(position).isEnabled());
 | 
			
		||||
        textView.setChecked(mWrapperList.get(position).isChecked());
 | 
			
		||||
        textView.setOnClickListener(l -> {
 | 
			
		||||
            textView.toggle();
 | 
			
		||||
            mWrapperList.get(position).setChecked(textView.isChecked());
 | 
			
		||||
        });
 | 
			
		||||
        return convertView;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,135 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 android.app.Dialog;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.content.pm.verify.domain.DomainVerificationManager;
 | 
			
		||||
import android.content.pm.verify.domain.DomainVerificationUserState;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.util.ArraySet;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import androidx.appcompat.app.AlertDialog;
 | 
			
		||||
import androidx.fragment.app.DialogFragment;
 | 
			
		||||
import androidx.fragment.app.Fragment;
 | 
			
		||||
import androidx.fragment.app.FragmentManager;
 | 
			
		||||
import androidx.lifecycle.ViewModelProviders;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
/** A customized {@link DialogFragment} with multiple checkboxes. */
 | 
			
		||||
public class SupportedLinksDialogFragment extends DialogFragment {
 | 
			
		||||
    private static final String TAG = "SupportedLinksDialogFrg";
 | 
			
		||||
    private static final String DLG_ID = "SupportedLinksDialog";
 | 
			
		||||
 | 
			
		||||
    private SupportedLinkViewModel mViewModel;
 | 
			
		||||
    private List<SupportedLinkWrapper> mSupportedLinkWrapperList;
 | 
			
		||||
    private String mPackage;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
        super.onCreate(savedInstanceState);
 | 
			
		||||
        mPackage = getArguments().getString(AppLaunchSettings.APP_PACKAGE_KEY);
 | 
			
		||||
        mViewModel = ViewModelProviders.of(this.getActivity()).get(SupportedLinkViewModel.class);
 | 
			
		||||
        mSupportedLinkWrapperList = mViewModel.getSupportedLinkWrapperList();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onDestroy() {
 | 
			
		||||
        super.onDestroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Dialog onCreateDialog(Bundle savedInstanceState) {
 | 
			
		||||
        final Context context = getActivity();
 | 
			
		||||
        final SupportedLinksAdapter adapter = new SupportedLinksAdapter(context,
 | 
			
		||||
                mSupportedLinkWrapperList);
 | 
			
		||||
        final AlertDialog.Builder builder = new AlertDialog
 | 
			
		||||
                .Builder(context)
 | 
			
		||||
                .setTitle(IntentPickerUtils.getCentralizedDialogTitle(getSupportedLinksTitle()))
 | 
			
		||||
                .setAdapter(adapter, /* listener= */ null)
 | 
			
		||||
                .setCancelable(true)
 | 
			
		||||
                .setPositiveButton(R.string.app_launch_supported_links_add, (dialog, id) -> {
 | 
			
		||||
                    //   addSelectedItems(((AlertDialog) dialog).getListView());
 | 
			
		||||
                    doSelectedAction();
 | 
			
		||||
                })
 | 
			
		||||
                .setNegativeButton(R.string.app_launch_dialog_cancel, /* listener= */ null);
 | 
			
		||||
        return builder.create();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Display the dialog. */
 | 
			
		||||
    public void showDialog(FragmentManager manager) {
 | 
			
		||||
        show(manager, DLG_ID);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getSupportedLinksTitle() {
 | 
			
		||||
        final int supportedLinksNo = mSupportedLinkWrapperList.size();
 | 
			
		||||
        return getResources().getQuantityString(
 | 
			
		||||
                R.plurals.app_launch_supported_links_title, supportedLinksNo, supportedLinksNo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void doSelectedAction() {
 | 
			
		||||
        final DomainVerificationManager manager = getActivity().getSystemService(
 | 
			
		||||
                DomainVerificationManager.class);
 | 
			
		||||
        final DomainVerificationUserState userState =
 | 
			
		||||
                IntentPickerUtils.getDomainVerificationUserState(manager, mPackage);
 | 
			
		||||
        if (userState == null || mSupportedLinkWrapperList == null) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        updateUserSelection(manager, userState);
 | 
			
		||||
        displaySelectedItem();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void updateUserSelection(DomainVerificationManager manager,
 | 
			
		||||
            DomainVerificationUserState userState) {
 | 
			
		||||
        final Set<String> domainSet = new ArraySet<>();
 | 
			
		||||
        for (SupportedLinkWrapper wrapper : mSupportedLinkWrapperList) {
 | 
			
		||||
            if (wrapper.isChecked()) {
 | 
			
		||||
                domainSet.add(wrapper.getHost());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (domainSet.size() > 0) {
 | 
			
		||||
            setDomainVerificationUserSelection(manager, userState.getIdentifier(),
 | 
			
		||||
                    domainSet, /* enabled= */true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void setDomainVerificationUserSelection(DomainVerificationManager manager,
 | 
			
		||||
            UUID identifier, Set<String> domainSet, boolean isEnabled) {
 | 
			
		||||
        try {
 | 
			
		||||
            manager.setDomainVerificationUserSelection(identifier, domainSet, isEnabled);
 | 
			
		||||
        } catch (PackageManager.NameNotFoundException e) {
 | 
			
		||||
            Log.w(TAG, "addSelectedItems : " + e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void displaySelectedItem() {
 | 
			
		||||
        final List<Fragment> fragments = getActivity().getSupportFragmentManager().getFragments();
 | 
			
		||||
        for (Fragment fragment : fragments) {
 | 
			
		||||
            if (fragment instanceof AppLaunchSettings) {
 | 
			
		||||
                ((AppLaunchSettings) fragment).addSelectedLinksPreference();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,95 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 android.content.Context;
 | 
			
		||||
import android.util.AttributeSet;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.widget.CheckBox;
 | 
			
		||||
 | 
			
		||||
import androidx.preference.PreferenceViewHolder;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
import com.android.settingslib.widget.TwoTargetPreference;
 | 
			
		||||
 | 
			
		||||
/** This customized VerifiedLinksPreference was belonged to Open by default page */
 | 
			
		||||
public class VerifiedLinksPreference extends TwoTargetPreference {
 | 
			
		||||
    private Context mContext;
 | 
			
		||||
    private View.OnClickListener mOnWidgetClickListener;
 | 
			
		||||
    private boolean mShowCheckBox;
 | 
			
		||||
 | 
			
		||||
    public VerifiedLinksPreference(Context context, AttributeSet attrs,
 | 
			
		||||
            int defStyleAttr, int defStyleRes) {
 | 
			
		||||
        super(context, attrs, defStyleAttr, defStyleRes);
 | 
			
		||||
        init(context);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public VerifiedLinksPreference(Context context, AttributeSet attrs, int defStyleAttr) {
 | 
			
		||||
        this(context, attrs, defStyleAttr, /* defStyleRes= */0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public VerifiedLinksPreference(Context context, AttributeSet attrs) {
 | 
			
		||||
        this(context, attrs, /* defStyleAttr= */ 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public VerifiedLinksPreference(Context context) {
 | 
			
		||||
        this(context, /* attrs= */ null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void init(Context context) {
 | 
			
		||||
        mContext = context;
 | 
			
		||||
        mOnWidgetClickListener = null;
 | 
			
		||||
        mShowCheckBox = true;
 | 
			
		||||
        setLayoutResource(R.layout.preference_checkable_two_target);
 | 
			
		||||
        setWidgetLayoutResource(R.layout.verified_links_widget);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Register a callback to be invoked when this widget is clicked.
 | 
			
		||||
     *
 | 
			
		||||
     * @param listener The callback that will run.
 | 
			
		||||
     */
 | 
			
		||||
    public void setWidgetFrameClickListener(View.OnClickListener listener) {
 | 
			
		||||
        mOnWidgetClickListener = listener;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Determine the visibility of the {@link CheckBox}. */
 | 
			
		||||
    public void setCheckBoxVisible(boolean isVisible) {
 | 
			
		||||
        mShowCheckBox = isVisible;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onBindViewHolder(PreferenceViewHolder view) {
 | 
			
		||||
        super.onBindViewHolder(view);
 | 
			
		||||
        final View settingsWidget = view.findViewById(android.R.id.widget_frame);
 | 
			
		||||
        final View divider = view.findViewById(R.id.two_target_divider);
 | 
			
		||||
        divider.setVisibility(View.VISIBLE);
 | 
			
		||||
        settingsWidget.setVisibility(View.VISIBLE);
 | 
			
		||||
        if (mOnWidgetClickListener != null) {
 | 
			
		||||
            settingsWidget.setOnClickListener(mOnWidgetClickListener);
 | 
			
		||||
        }
 | 
			
		||||
        final View checkboxContainer = view.findViewById(R.id.checkbox_container);
 | 
			
		||||
        final View parentView = (View) checkboxContainer.getParent();
 | 
			
		||||
        parentView.setEnabled(false);
 | 
			
		||||
        parentView.setClickable(false);
 | 
			
		||||
        CheckBox checkBox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox);
 | 
			
		||||
        if (checkBox != null) {
 | 
			
		||||
            checkBox.setChecked(true);
 | 
			
		||||
            checkBox.setVisibility(mShowCheckBox ? View.VISIBLE : View.INVISIBLE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -28,7 +28,7 @@ import androidx.preference.PreferenceScreen;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
import com.android.settings.applications.AppInfoBase;
 | 
			
		||||
import com.android.settings.applications.AppLaunchSettings;
 | 
			
		||||
import com.android.settings.applications.intentpicker.AppLaunchSettings;
 | 
			
		||||
import com.android.settings.core.BasePreferenceController;
 | 
			
		||||
import com.android.settingslib.applications.ApplicationsState;
 | 
			
		||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ import android.content.pm.ResolveInfo;
 | 
			
		||||
import androidx.preference.Preference;
 | 
			
		||||
import androidx.preference.PreferenceScreen;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.applications.AppLaunchSettings;
 | 
			
		||||
import com.android.settings.applications.intentpicker.AppLaunchSettings;
 | 
			
		||||
import com.android.settingslib.applications.AppUtils;
 | 
			
		||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
 | 
			
		||||
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user