Add Private space Delete settings page inside PS settings page
Contains implementation of settings page for Delete private space controller inside private space settings page. - On selecting to delete private space displays list of account signed in to private profile and deletes the private space after authentication. - Shows a toast message after private space is deleted - Adds dependency for setupdesgin loading layout to show a loading screen while deletion of private space is in progress. Recording Link : b/318383729 go/ss/4Aq3rmbSGHMHesK.png Bug: 318383729 Test: atest DeletePrivateSpaceControllerTest Change-Id: Ia1730915e2469b47823c507f9ef6cd8f63c99baf
This commit is contained in:
		@@ -109,6 +109,7 @@ android_library {
 | 
			
		||||
        "statslog-settings",
 | 
			
		||||
        "androidx.test.rules",
 | 
			
		||||
        "telephony_flags_core_java_lib",
 | 
			
		||||
        "setupdesign-lottie-loading-layout",
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    plugins: ["androidx.room_room-compiler-plugin"],
 | 
			
		||||
 
 | 
			
		||||
@@ -5070,6 +5070,11 @@
 | 
			
		||||
 | 
			
		||||
        <activity android:name=".privatespace.PrivateProfileContextHelperActivity" android:exported="false"/>
 | 
			
		||||
 | 
			
		||||
        <activity android:name=".privatespace.delete.PrivateSpaceDeleteActivity"
 | 
			
		||||
                  android:label="@string/private_space_delete_header"
 | 
			
		||||
                  android:exported="false">
 | 
			
		||||
        </activity>
 | 
			
		||||
 | 
			
		||||
        <activity-alias android:name="UsageStatsActivity"
 | 
			
		||||
                        android:exported="true"
 | 
			
		||||
                        android:label="@string/testing_usage_stats"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								res/layout/private_space_confirm_deletion.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								res/layout/private_space_confirm_deletion.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
  ~ Copyright (C) 2024 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.
 | 
			
		||||
  -->
 | 
			
		||||
 | 
			
		||||
<com.google.android.setupdesign.GlifLoadingLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
    android:id="@+id/private_space_delete_confirm"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent"
 | 
			
		||||
    android:orientation="vertical"
 | 
			
		||||
    android:icon="@drawable/ic_delete_accent"
 | 
			
		||||
    app:sudUsePartnerHeavyTheme="true"
 | 
			
		||||
    app:sudIllustrationType="default"
 | 
			
		||||
    app:sudDescriptionText = "@string/private_space_confirm_deletion_summary"
 | 
			
		||||
    app:sucHeaderText="@string/private_space_confirm_deletion_header">
 | 
			
		||||
</com.google.android.setupdesign.GlifLoadingLayout>
 | 
			
		||||
							
								
								
									
										68
									
								
								res/layout/private_space_delete.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								res/layout/private_space_delete.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
  ~ Copyright (C) 2024 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.
 | 
			
		||||
  -->
 | 
			
		||||
 | 
			
		||||
<com.google.android.setupdesign.GlifLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
    android:id="@+id/private_space_delete_layout"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent"
 | 
			
		||||
    android:orientation="vertical"
 | 
			
		||||
    android:icon="@drawable/ic_delete_accent"
 | 
			
		||||
    app:sucHeaderText="@string/private_space_delete_header">
 | 
			
		||||
 | 
			
		||||
    <ScrollView
 | 
			
		||||
        android:id="@+id/private_space_delete_scrollview"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
        <LinearLayout
 | 
			
		||||
            android:id="@+id/private_space_delete_container"
 | 
			
		||||
            style="@style/SudContentFrame"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginTop="16dp"
 | 
			
		||||
            android:orientation="vertical">
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                style="@style/TextAppearance.PreferenceTitle.SettingsLib"
 | 
			
		||||
                android:id="@+id/sud_layout_subtitle"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:text="@string/private_space_delete_summary"/>
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                android:id="@+id/accounts_label"
 | 
			
		||||
                style="@style/TextAppearance.PreferenceTitle.SettingsLib"
 | 
			
		||||
                android:layout_marginTop="20dp"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:visibility="gone"
 | 
			
		||||
                android:text="@string/private_space_accounts"/>
 | 
			
		||||
            <LinearLayout
 | 
			
		||||
                android:id="@+id/accounts"
 | 
			
		||||
                android:layout_marginTop="20dp"
 | 
			
		||||
                android:layout_width="wrap_content"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:orientation="vertical"
 | 
			
		||||
                android:visibility="gone">
 | 
			
		||||
                <!-- Do not add any children here as they will be removed in the MainClear.java
 | 
			
		||||
                   code. A list of accounts will be inserted programmatically. -->
 | 
			
		||||
            </LinearLayout>
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
    </ScrollView>
 | 
			
		||||
</com.google.android.setupdesign.GlifLayout>
 | 
			
		||||
							
								
								
									
										31
									
								
								res/navigation/private_space_delete_nav.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								res/navigation/private_space_delete_nav.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
<!--
 | 
			
		||||
  ~ Copyright (C) 2024 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.
 | 
			
		||||
  -->
 | 
			
		||||
 | 
			
		||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
            xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
            android:id="@+id/private_space_delete_nav"
 | 
			
		||||
            app:startDestination="@id/ps_delete_fragment">
 | 
			
		||||
    <fragment android:id="@+id/ps_delete_fragment"
 | 
			
		||||
              android:name="com.android.settings.privatespace.delete.PrivateSpaceDeleteFragment"
 | 
			
		||||
              android:label="fragment_ps_delete">
 | 
			
		||||
        <action
 | 
			
		||||
            android:id="@+id/action_authenticate_delete"
 | 
			
		||||
            app:destination="@id/ps_delete_progress_fragment"/>
 | 
			
		||||
    </fragment>
 | 
			
		||||
    <fragment android:id="@+id/ps_delete_progress_fragment"
 | 
			
		||||
              android:name="com.android.settings.privatespace.delete.PrivateSpaceDeletionProgressFragment"
 | 
			
		||||
              android:label="fragment_ps_auto_advance"/>
 | 
			
		||||
</navigation>
 | 
			
		||||
@@ -1280,8 +1280,20 @@
 | 
			
		||||
    <string name="privatespace_hide_on_summary">On</string>
 | 
			
		||||
    <!-- System category for the Private Space page. [CHAR LIMIT=30] -->
 | 
			
		||||
    <string name="private_space_category_system">System</string>
 | 
			
		||||
    <!-- Title for the preference to delete Private Space. [CHAR LIMIT=60] -->
 | 
			
		||||
    <string name="private_space_delete_title">Delete Private Space</string>
 | 
			
		||||
    <!-- Title for the preference to delete Private Space. [CHAR LIMIT=40] -->
 | 
			
		||||
    <string name="private_space_delete_title">Delete private space</string>
 | 
			
		||||
    <!-- Title for the delete private space page. [CHAR LIMIT=40] -->
 | 
			
		||||
    <string name="private_space_delete_header">Delete private space?</string>
 | 
			
		||||
    <!-- Description for hide Private Space settings page. [CHAR LIMIT=NONE] -->
 | 
			
		||||
    <string name="private_space_delete_summary">Your private space will be removed from your device. All private apps and data will be deleted. You can’t undo this action.</string>
 | 
			
		||||
    <!-- Text for the accounts added to private space that will be removed. [CHAR LIMIT=90] -->
 | 
			
		||||
    <string name="private_space_accounts">The following accounts will be removed from your private space:</string>
 | 
			
		||||
    <!-- Label for private space delete button [CHAR LIMIT=30] -->
 | 
			
		||||
    <string name="private_space_delete_button_label">Delete</string>
 | 
			
		||||
    <!-- Title for the private space delete confirmation page. [CHAR LIMIT=40] -->
 | 
			
		||||
    <string name="private_space_confirm_deletion_header">Deleting private space\u2026</string>
 | 
			
		||||
    <!-- Description for private space delete confirmation page that mentions it will take a few moments. [CHAR LIMIT=40] -->
 | 
			
		||||
    <string name="private_space_confirm_deletion_summary">This will take a few moments</string>
 | 
			
		||||
    <!-- Toast to show when the private space was deleted. [CHAR LIMIT=NONE] -->
 | 
			
		||||
    <string name="private_space_deleted">Private Space successfully deleted</string>
 | 
			
		||||
    <!-- Toast to show when the private space could not be deleted. [CHAR LIMIT=NONE] -->
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@
 | 
			
		||||
        <Preference
 | 
			
		||||
            android:key="private_space_delete"
 | 
			
		||||
            android:title="@string/private_space_delete_title"
 | 
			
		||||
            settings:controller="com.android.settings.privatespace.DeletePrivateSpaceController"
 | 
			
		||||
            settings:controller="com.android.settings.privatespace.delete.DeletePrivateSpaceController"
 | 
			
		||||
            settings:searchable="false" />
 | 
			
		||||
 | 
			
		||||
    </PreferenceCategory>
 | 
			
		||||
 
 | 
			
		||||
@@ -169,6 +169,8 @@ import com.android.settings.print.PrintJobSettingsFragment;
 | 
			
		||||
import com.android.settings.print.PrintSettingsFragment;
 | 
			
		||||
import com.android.settings.privacy.PrivacyControlsFragment;
 | 
			
		||||
import com.android.settings.privacy.PrivacyDashboardFragment;
 | 
			
		||||
import com.android.settings.privatespace.delete.PrivateSpaceDeleteFragment;
 | 
			
		||||
import com.android.settings.privatespace.delete.PrivateSpaceDeletionProgressFragment;
 | 
			
		||||
import com.android.settings.privatespace.onelock.PrivateSpaceBiometricSettings;
 | 
			
		||||
import com.android.settings.regionalpreferences.RegionalPreferencesEntriesFragment;
 | 
			
		||||
import com.android.settings.safetycenter.MoreSecurityPrivacyFragment;
 | 
			
		||||
@@ -271,6 +273,8 @@ public class SettingsGateway {
 | 
			
		||||
            CombinedBiometricSettings.class.getName(),
 | 
			
		||||
            CombinedBiometricProfileSettings.class.getName(),
 | 
			
		||||
            PrivateSpaceBiometricSettings.class.getName(),
 | 
			
		||||
            PrivateSpaceDeleteFragment.class.getName(),
 | 
			
		||||
            PrivateSpaceDeletionProgressFragment.class.getName(),
 | 
			
		||||
            SwipeToNotificationSettings.class.getName(),
 | 
			
		||||
            DoubleTapPowerSettings.class.getName(),
 | 
			
		||||
            DoubleTapScreenSettings.class.getName(),
 | 
			
		||||
 
 | 
			
		||||
@@ -1,90 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 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.privatespace;
 | 
			
		||||
 | 
			
		||||
import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_INTERNAL;
 | 
			
		||||
import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_NONE;
 | 
			
		||||
import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_NO_PRIVATE_SPACE;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.text.TextUtils;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
 | 
			
		||||
import androidx.preference.Preference;
 | 
			
		||||
 | 
			
		||||
import com.android.internal.annotations.VisibleForTesting;
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
import com.android.settings.core.BasePreferenceController;
 | 
			
		||||
 | 
			
		||||
/** Controller to delete the private space from the PS Settings page */
 | 
			
		||||
public class DeletePrivateSpaceController extends BasePreferenceController {
 | 
			
		||||
    private static final String TAG = "DeletePrivateSpaceController";
 | 
			
		||||
    private final PrivateSpaceMaintainer mPrivateSpaceMaintainer;
 | 
			
		||||
 | 
			
		||||
    static class Injector {
 | 
			
		||||
        PrivateSpaceMaintainer injectPrivateSpaceMaintainer(Context context) {
 | 
			
		||||
            return PrivateSpaceMaintainer.getInstance(context);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public DeletePrivateSpaceController(Context context, String preferenceKey) {
 | 
			
		||||
        this(context, preferenceKey, new Injector());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DeletePrivateSpaceController(Context context, String preferenceKey, Injector injector) {
 | 
			
		||||
        super(context, preferenceKey);
 | 
			
		||||
        mPrivateSpaceMaintainer = injector.injectPrivateSpaceMaintainer(context);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getAvailabilityStatus() {
 | 
			
		||||
        return android.os.Flags.allowPrivateProfile() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean handlePreferenceTreeClick(Preference preference) {
 | 
			
		||||
        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        PrivateSpaceMaintainer.ErrorDeletingPrivateSpace error =
 | 
			
		||||
                mPrivateSpaceMaintainer.deletePrivateSpace();
 | 
			
		||||
        if (error == DELETE_PS_ERROR_NONE) {
 | 
			
		||||
            showSuccessfulDeletionToast();
 | 
			
		||||
        } else if (error == DELETE_PS_ERROR_INTERNAL) {
 | 
			
		||||
            showDeletionInternalErrorToast();
 | 
			
		||||
        } else if (error == DELETE_PS_ERROR_NO_PRIVATE_SPACE) {
 | 
			
		||||
            // Ideally this should never happen as PS Settings is not available when there's no
 | 
			
		||||
            // Private Profile.
 | 
			
		||||
            Log.e(TAG, "Unexpected attempt to delete non-existent PS");
 | 
			
		||||
        }
 | 
			
		||||
        return super.handlePreferenceTreeClick(preference);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Shows a toast saying that the private space was deleted */
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    public void showSuccessfulDeletionToast() {
 | 
			
		||||
        Toast.makeText(mContext, R.string.private_space_deleted, Toast.LENGTH_SHORT).show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Shows a toast saying that the private space could not be deleted */
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    public void showDeletionInternalErrorToast() {
 | 
			
		||||
        Toast.makeText(mContext, R.string.private_space_delete_failed, Toast.LENGTH_SHORT).show();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -75,7 +75,8 @@ public class PrivateSpaceMaintainer {
 | 
			
		||||
     *
 | 
			
		||||
     * <p> This method should be used by the Private Space Setup Flow ONLY.
 | 
			
		||||
     */
 | 
			
		||||
    final synchronized boolean createPrivateSpace() {
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    public final synchronized boolean createPrivateSpace() {
 | 
			
		||||
        if (!Flags.allowPrivateProfile()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,53 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 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.privatespace.delete;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.NonNull;
 | 
			
		||||
import androidx.preference.Preference;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.core.BasePreferenceController;
 | 
			
		||||
 | 
			
		||||
/** Controller to delete the private space from the PS Settings page */
 | 
			
		||||
public class DeletePrivateSpaceController extends BasePreferenceController {
 | 
			
		||||
    private static final String TAG = "PrivateSpaceDeleteCtrl";
 | 
			
		||||
 | 
			
		||||
    public DeletePrivateSpaceController(@NonNull Context context, @NonNull String preferenceKey) {
 | 
			
		||||
        super(context, preferenceKey);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getAvailabilityStatus() {
 | 
			
		||||
        return android.os.Flags.allowPrivateProfile() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean handlePreferenceTreeClick(@NonNull Preference preference) {
 | 
			
		||||
        if (mPreferenceKey.equals(preference.getKey())) {
 | 
			
		||||
            startPrivateSpaceDeleteActivity();
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void startPrivateSpaceDeleteActivity() {
 | 
			
		||||
        final Intent intent = new Intent(mContext, PrivateSpaceDeleteActivity.class);
 | 
			
		||||
        mContext.startActivity(intent);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2024 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.privatespace.delete;
 | 
			
		||||
 | 
			
		||||
import android.app.settings.SettingsEnums;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
 | 
			
		||||
import androidx.navigation.fragment.NavHostFragment;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
import com.android.settings.SetupWizardUtils;
 | 
			
		||||
import com.android.settings.core.InstrumentedActivity;
 | 
			
		||||
 | 
			
		||||
import com.google.android.setupdesign.util.ThemeHelper;
 | 
			
		||||
 | 
			
		||||
public class PrivateSpaceDeleteActivity extends InstrumentedActivity {
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getMetricsCategory() {
 | 
			
		||||
        return SettingsEnums.PRIVATE_SPACE_SETTINGS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
        if (!android.os.Flags.allowPrivateProfile()) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        setTheme(SetupWizardUtils.getTheme(this, getIntent()));
 | 
			
		||||
        ThemeHelper.trySetDynamicColor(this);
 | 
			
		||||
        super.onCreate(savedInstanceState);
 | 
			
		||||
        setContentView(R.layout.privatespace_setup_root);
 | 
			
		||||
        NavHostFragment navHostFragment =
 | 
			
		||||
                (NavHostFragment)
 | 
			
		||||
                        getSupportFragmentManager().findFragmentById(R.id.ps_nav_host_fragment);
 | 
			
		||||
        navHostFragment.getNavController().setGraph(R.navigation.private_space_delete_nav);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,172 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 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.privatespace.delete;
 | 
			
		||||
 | 
			
		||||
import android.accounts.Account;
 | 
			
		||||
import android.accounts.AccountManager;
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.app.settings.SettingsEnums;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.graphics.drawable.Drawable;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.UserHandle;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
import android.widget.ImageView;
 | 
			
		||||
import android.widget.LinearLayout;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.NonNull;
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
import androidx.navigation.fragment.NavHostFragment;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
import com.android.settings.core.InstrumentedFragment;
 | 
			
		||||
import com.android.settings.password.ChooseLockSettingsHelper;
 | 
			
		||||
import com.android.settings.privatespace.PrivateSpaceMaintainer;
 | 
			
		||||
import com.android.settingslib.accounts.AuthenticatorHelper;
 | 
			
		||||
 | 
			
		||||
import com.google.android.setupcompat.template.FooterBarMixin;
 | 
			
		||||
import com.google.android.setupcompat.template.FooterButton;
 | 
			
		||||
import com.google.android.setupdesign.GlifLayout;
 | 
			
		||||
 | 
			
		||||
/** Fragment to delete private space that lists the accounts logged in to the private profile. */
 | 
			
		||||
public class PrivateSpaceDeleteFragment extends InstrumentedFragment {
 | 
			
		||||
    private static final String TAG = "PrivateSpaceDeleteFrag";
 | 
			
		||||
    private View mContentView;
 | 
			
		||||
    private static final int CREDENTIAL_CONFIRM_REQUEST = 1;
 | 
			
		||||
    @Nullable private UserHandle mPrivateUserHandle;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate(@Nullable Bundle icicle) {
 | 
			
		||||
        if (android.os.Flags.allowPrivateProfile()) {
 | 
			
		||||
            super.onCreate(icicle);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onStart() {
 | 
			
		||||
        super.onStart();
 | 
			
		||||
        if (PrivateSpaceMaintainer.getInstance(getContext()).isPrivateSpaceLocked()) {
 | 
			
		||||
            getActivity().finish();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getMetricsCategory() {
 | 
			
		||||
        return SettingsEnums.PRIVATE_SPACE_SETTINGS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private View.OnClickListener startAuthenticationForDelete() {
 | 
			
		||||
        return v -> {
 | 
			
		||||
            final ChooseLockSettingsHelper.Builder builder =
 | 
			
		||||
                    new ChooseLockSettingsHelper.Builder(getActivity(), this);
 | 
			
		||||
            if (mPrivateUserHandle != null) {
 | 
			
		||||
                builder.setRequestCode(CREDENTIAL_CONFIRM_REQUEST)
 | 
			
		||||
                        .setUserId(mPrivateUserHandle.getIdentifier())
 | 
			
		||||
                        .show();
 | 
			
		||||
            } else {
 | 
			
		||||
                Log.e(TAG, "Private space user handle cannot be null");
 | 
			
		||||
                getActivity().finish();
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @NonNull
 | 
			
		||||
    @Override
 | 
			
		||||
    public View onCreateView(
 | 
			
		||||
            @NonNull LayoutInflater inflater,
 | 
			
		||||
            @Nullable ViewGroup container,
 | 
			
		||||
            @Nullable Bundle savedInstanceState) {
 | 
			
		||||
        mPrivateUserHandle =
 | 
			
		||||
                PrivateSpaceMaintainer.getInstance(getContext()).getPrivateProfileHandle();
 | 
			
		||||
        if (mPrivateUserHandle == null) {
 | 
			
		||||
            Log.e(TAG, "Private space user handle cannot be null");
 | 
			
		||||
            getActivity().finish();
 | 
			
		||||
        }
 | 
			
		||||
        mContentView = inflater.inflate(R.layout.private_space_delete, container, false);
 | 
			
		||||
        final GlifLayout layout = mContentView.findViewById(R.id.private_space_delete_layout);
 | 
			
		||||
        final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
 | 
			
		||||
        final Activity activity = getActivity();
 | 
			
		||||
        mixin.setPrimaryButton(
 | 
			
		||||
                new FooterButton.Builder(activity)
 | 
			
		||||
                        .setText(R.string.private_space_delete_button_label)
 | 
			
		||||
                        .setListener(startAuthenticationForDelete())
 | 
			
		||||
                        .setButtonType(FooterButton.ButtonType.OTHER)
 | 
			
		||||
                        .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
 | 
			
		||||
                        .build());
 | 
			
		||||
        mixin.setSecondaryButton(
 | 
			
		||||
                new FooterButton.Builder(activity)
 | 
			
		||||
                        .setText(android.R.string.cancel)
 | 
			
		||||
                        .setListener(view -> activity.onBackPressed())
 | 
			
		||||
                        .setButtonType(FooterButton.ButtonType.CANCEL)
 | 
			
		||||
                        .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
 | 
			
		||||
                        .build());
 | 
			
		||||
 | 
			
		||||
        loadPrivateProfileAccountList();
 | 
			
		||||
        return mContentView;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void loadPrivateProfileAccountList() {
 | 
			
		||||
        View accountsLabel = mContentView.findViewById(R.id.accounts_label);
 | 
			
		||||
        LinearLayout contents = (LinearLayout) mContentView.findViewById(R.id.accounts);
 | 
			
		||||
        contents.removeAllViews();
 | 
			
		||||
 | 
			
		||||
        Context context = getActivity();
 | 
			
		||||
 | 
			
		||||
        AccountManager accountManager = AccountManager.get(context);
 | 
			
		||||
 | 
			
		||||
        LayoutInflater inflater = context.getSystemService(LayoutInflater.class);
 | 
			
		||||
 | 
			
		||||
        final AuthenticatorHelper helper =
 | 
			
		||||
                new AuthenticatorHelper(context, mPrivateUserHandle, null);
 | 
			
		||||
        final String[] accountTypes = helper.getEnabledAccountTypes();
 | 
			
		||||
 | 
			
		||||
        for (String type : accountTypes) {
 | 
			
		||||
            final String accountType = type;
 | 
			
		||||
            final Account[] accounts =
 | 
			
		||||
                    accountManager.getAccountsByTypeAsUser(accountType, mPrivateUserHandle);
 | 
			
		||||
            Drawable icon = helper.getDrawableForType(getContext(), accountType);
 | 
			
		||||
            if (icon == null) {
 | 
			
		||||
                icon = context.getPackageManager().getDefaultActivityIcon();
 | 
			
		||||
            }
 | 
			
		||||
            for (Account account : accounts) {
 | 
			
		||||
                View child = inflater.inflate(R.layout.main_clear_account, contents, false);
 | 
			
		||||
                child.<ImageView>findViewById(android.R.id.icon).setImageDrawable(icon);
 | 
			
		||||
                child.<TextView>findViewById(android.R.id.title).setText(account.name);
 | 
			
		||||
                contents.addView(child);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (contents.getChildCount() > 0) {
 | 
			
		||||
            accountsLabel.setVisibility(View.VISIBLE);
 | 
			
		||||
            contents.setVisibility(View.VISIBLE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
 | 
			
		||||
        super.onActivityResult(requestCode, resultCode, data);
 | 
			
		||||
        if (requestCode == CREDENTIAL_CONFIRM_REQUEST && resultCode == Activity.RESULT_OK) {
 | 
			
		||||
            NavHostFragment.findNavController(PrivateSpaceDeleteFragment.this)
 | 
			
		||||
                    .navigate(R.id.action_authenticate_delete);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,143 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2024 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.privatespace.delete;
 | 
			
		||||
 | 
			
		||||
import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_INTERNAL;
 | 
			
		||||
import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_NONE;
 | 
			
		||||
 | 
			
		||||
import android.app.settings.SettingsEnums;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.Handler;
 | 
			
		||||
import android.os.Looper;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
 | 
			
		||||
import androidx.activity.OnBackPressedCallback;
 | 
			
		||||
import androidx.annotation.NonNull;
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
import com.android.internal.annotations.VisibleForTesting;
 | 
			
		||||
import com.android.settings.R;
 | 
			
		||||
import com.android.settings.core.InstrumentedFragment;
 | 
			
		||||
import com.android.settings.privatespace.PrivateSpaceMaintainer;
 | 
			
		||||
 | 
			
		||||
/** Fragment to show loading animation screen while deleting private space. */
 | 
			
		||||
public class PrivateSpaceDeletionProgressFragment extends InstrumentedFragment {
 | 
			
		||||
    private static final String TAG = "PrivateSpaceDeleteProg";
 | 
			
		||||
    private static final int PRIVATE_SPACE_DELETE_POST_DELAY_MS = 1000;
 | 
			
		||||
    private Handler mHandler;
 | 
			
		||||
    private PrivateSpaceMaintainer mPrivateSpaceMaintainer;
 | 
			
		||||
    private Runnable mDeletePrivateSpace =
 | 
			
		||||
            new Runnable() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run() {
 | 
			
		||||
                    deletePrivateSpace();
 | 
			
		||||
                    getActivity().finish();
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
    static class Injector {
 | 
			
		||||
        PrivateSpaceMaintainer injectPrivateSpaceMaintainer(Context context) {
 | 
			
		||||
            return PrivateSpaceMaintainer.getInstance(context);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate(@Nullable Bundle savedInstanceState) {
 | 
			
		||||
        if (android.os.Flags.allowPrivateProfile()) {
 | 
			
		||||
            super.onCreate(savedInstanceState);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getMetricsCategory() {
 | 
			
		||||
        return SettingsEnums.PRIVATE_SPACE_SETTINGS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @NonNull
 | 
			
		||||
    @Override
 | 
			
		||||
    public View onCreateView(
 | 
			
		||||
            @NonNull LayoutInflater inflater,
 | 
			
		||||
            @Nullable ViewGroup container,
 | 
			
		||||
            @Nullable Bundle savedInstanceState) {
 | 
			
		||||
        mPrivateSpaceMaintainer =
 | 
			
		||||
                new PrivateSpaceDeletionProgressFragment.Injector()
 | 
			
		||||
                        .injectPrivateSpaceMaintainer(getActivity().getApplicationContext());
 | 
			
		||||
        if (!mPrivateSpaceMaintainer.doesPrivateSpaceExist()) {
 | 
			
		||||
            // Ideally this should never happen as PS Settings is not available when there's no
 | 
			
		||||
            // Private Profile.
 | 
			
		||||
            Log.e(TAG, "Unexpected attempt to delete non-existent PS");
 | 
			
		||||
            getActivity().finish();
 | 
			
		||||
        }
 | 
			
		||||
        View contentView =
 | 
			
		||||
                inflater.inflate(R.layout.private_space_confirm_deletion, container, false);
 | 
			
		||||
        OnBackPressedCallback callback =
 | 
			
		||||
                new OnBackPressedCallback(true /* enabled by default */) {
 | 
			
		||||
                    @Override
 | 
			
		||||
                    public void handleOnBackPressed() {
 | 
			
		||||
                        // Handle the back button event. We intentionally don't want to allow back
 | 
			
		||||
                        // button to work in this screen during the setup flow.
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
        requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
 | 
			
		||||
        mHandler = new Handler(Looper.getMainLooper());
 | 
			
		||||
        // Ensures screen visibility to user by introducing a 1-second delay before deleting private
 | 
			
		||||
        // space.
 | 
			
		||||
        mHandler.postDelayed(mDeletePrivateSpace, PRIVATE_SPACE_DELETE_POST_DELAY_MS);
 | 
			
		||||
        return contentView;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onDestroy() {
 | 
			
		||||
        mHandler.removeCallbacks(mDeletePrivateSpace);
 | 
			
		||||
        super.onDestroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Deletes private space and shows a toast message */
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    public void deletePrivateSpace() {
 | 
			
		||||
        PrivateSpaceMaintainer.ErrorDeletingPrivateSpace error =
 | 
			
		||||
                mPrivateSpaceMaintainer.deletePrivateSpace();
 | 
			
		||||
        if (error == DELETE_PS_ERROR_NONE) {
 | 
			
		||||
            showSuccessfulDeletionToast();
 | 
			
		||||
        } else if (error == DELETE_PS_ERROR_INTERNAL) {
 | 
			
		||||
            showDeletionInternalErrorToast();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    public void setPrivateSpaceMaintainer(@NonNull Injector injector) {
 | 
			
		||||
        mPrivateSpaceMaintainer = injector.injectPrivateSpaceMaintainer(getActivity());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Shows a toast saying that the private space was deleted */
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    public void showSuccessfulDeletionToast() {
 | 
			
		||||
        Toast.makeText(getContext(), R.string.private_space_deleted, Toast.LENGTH_SHORT).show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Shows a toast saying that the private space could not be deleted */
 | 
			
		||||
    @VisibleForTesting
 | 
			
		||||
    public void showDeletionInternalErrorToast() {
 | 
			
		||||
        Toast.makeText(getContext(), R.string.private_space_delete_failed, Toast.LENGTH_SHORT)
 | 
			
		||||
                .show();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,108 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 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.privatespace;
 | 
			
		||||
 | 
			
		||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
 | 
			
		||||
import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_INTERNAL;
 | 
			
		||||
import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_NONE;
 | 
			
		||||
import static com.google.common.truth.Truth.assertThat;
 | 
			
		||||
import static org.mockito.Mockito.doNothing;
 | 
			
		||||
import static org.mockito.Mockito.doReturn;
 | 
			
		||||
import static org.mockito.Mockito.verify;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
 | 
			
		||||
import androidx.preference.Preference;
 | 
			
		||||
import androidx.test.core.app.ApplicationProvider;
 | 
			
		||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
 | 
			
		||||
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.Mockito;
 | 
			
		||||
import org.mockito.MockitoAnnotations;
 | 
			
		||||
 | 
			
		||||
@RunWith(AndroidJUnit4.class)
 | 
			
		||||
public class DeletePrivateSpaceControllerTest {
 | 
			
		||||
    @Mock private PrivateSpaceMaintainer mPrivateSpaceMaintainer;
 | 
			
		||||
    @Mock private Context mContext;
 | 
			
		||||
 | 
			
		||||
    private Preference mPreference;
 | 
			
		||||
    private DeletePrivateSpaceController mDeletePrivateSpaceController;
 | 
			
		||||
 | 
			
		||||
    /** Required setup before a test. */
 | 
			
		||||
    @Before
 | 
			
		||||
    public void setUp() {
 | 
			
		||||
        MockitoAnnotations.initMocks(this);
 | 
			
		||||
        mContext = ApplicationProvider.getApplicationContext();
 | 
			
		||||
        final String preferenceKey = "private_space_delete";
 | 
			
		||||
 | 
			
		||||
        mPreference = new Preference(ApplicationProvider.getApplicationContext());
 | 
			
		||||
        mPreference.setKey(preferenceKey);
 | 
			
		||||
 | 
			
		||||
        mDeletePrivateSpaceController =
 | 
			
		||||
                new DeletePrivateSpaceController(
 | 
			
		||||
                        mContext,
 | 
			
		||||
                        preferenceKey,
 | 
			
		||||
                        new DeletePrivateSpaceController.Injector() {
 | 
			
		||||
                            @Override
 | 
			
		||||
                            PrivateSpaceMaintainer injectPrivateSpaceMaintainer(Context context) {
 | 
			
		||||
                                return mPrivateSpaceMaintainer;
 | 
			
		||||
                            }
 | 
			
		||||
                        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Tests that the controller is always available. */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void getAvailabilityStatus_returnsAvailable() {
 | 
			
		||||
        assertThat(mDeletePrivateSpaceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Tests that on click it attempts to delete the PS. */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void handlePreferenceTreeClick_attemptsToDeletePrivateSpace() {
 | 
			
		||||
        doReturn(DELETE_PS_ERROR_NONE).when(mPrivateSpaceMaintainer).deletePrivateSpace();
 | 
			
		||||
        DeletePrivateSpaceController spy = Mockito.spy(mDeletePrivateSpaceController);
 | 
			
		||||
        doNothing().when(spy).showSuccessfulDeletionToast();
 | 
			
		||||
        spy.handlePreferenceTreeClick(mPreference);
 | 
			
		||||
 | 
			
		||||
        verify(mPrivateSpaceMaintainer).deletePrivateSpace();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Tests that on deletion of PS relevant toast is shown. */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void handlePreferenceTreeClick_onDeletion_showsDeletedToast() {
 | 
			
		||||
        doReturn(DELETE_PS_ERROR_NONE).when(mPrivateSpaceMaintainer).deletePrivateSpace();
 | 
			
		||||
        DeletePrivateSpaceController spy = Mockito.spy(mDeletePrivateSpaceController);
 | 
			
		||||
        doNothing().when(spy).showSuccessfulDeletionToast();
 | 
			
		||||
        spy.handlePreferenceTreeClick(mPreference);
 | 
			
		||||
 | 
			
		||||
        verify(spy).showSuccessfulDeletionToast();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Tests that on failing to delete the PS relevant toast is shown. */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void handlePreferenceTreeClick_onDeletionError_showsDeletionFailedToast() {
 | 
			
		||||
        doReturn(DELETE_PS_ERROR_INTERNAL).when(mPrivateSpaceMaintainer).deletePrivateSpace();
 | 
			
		||||
        DeletePrivateSpaceController spy = Mockito.spy(mDeletePrivateSpaceController);
 | 
			
		||||
        doNothing().when(spy).showDeletionInternalErrorToast();
 | 
			
		||||
        spy.handlePreferenceTreeClick(mPreference);
 | 
			
		||||
 | 
			
		||||
        verify(spy).showDeletionInternalErrorToast();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,74 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2024 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.privatespace.delete;
 | 
			
		||||
 | 
			
		||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
 | 
			
		||||
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
 | 
			
		||||
 | 
			
		||||
import static com.google.common.truth.Truth.assertThat;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.platform.test.flag.junit.SetFlagsRule;
 | 
			
		||||
 | 
			
		||||
import androidx.preference.Preference;
 | 
			
		||||
import androidx.test.core.app.ApplicationProvider;
 | 
			
		||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
 | 
			
		||||
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Rule;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.MockitoAnnotations;
 | 
			
		||||
 | 
			
		||||
@RunWith(AndroidJUnit4.class)
 | 
			
		||||
public class DeletePrivateSpaceControllerTest {
 | 
			
		||||
    @Mock private Context mContext;
 | 
			
		||||
    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 | 
			
		||||
    private Preference mPreference;
 | 
			
		||||
    private DeletePrivateSpaceController mDeletePrivateSpaceController;
 | 
			
		||||
 | 
			
		||||
    /** Required setup before a test. */
 | 
			
		||||
    @Before
 | 
			
		||||
    public void setUp() {
 | 
			
		||||
        MockitoAnnotations.initMocks(this);
 | 
			
		||||
        mContext = ApplicationProvider.getApplicationContext();
 | 
			
		||||
        final String preferenceKey = "private_space_delete";
 | 
			
		||||
 | 
			
		||||
        mPreference = new Preference(ApplicationProvider.getApplicationContext());
 | 
			
		||||
        mPreference.setKey(preferenceKey);
 | 
			
		||||
 | 
			
		||||
        mDeletePrivateSpaceController = new DeletePrivateSpaceController(mContext, preferenceKey);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Tests that the controller is available when private space flag is enabled. */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void getAvailabilityStatus_whenPrivateFlagEnabled_returnsAvailable() {
 | 
			
		||||
        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
 | 
			
		||||
 | 
			
		||||
        assertThat(mDeletePrivateSpaceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Tests that the controller is not available when private space flag is disabled. */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void getAvailabilityStatus_whenPrivateFlagDisabled_returnsUnsupportedOnDevice() {
 | 
			
		||||
        mSetFlagsRule.disableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
 | 
			
		||||
 | 
			
		||||
        assertThat(mDeletePrivateSpaceController.getAvailabilityStatus())
 | 
			
		||||
                .isEqualTo(UNSUPPORTED_ON_DEVICE);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2024 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.privatespace.delete;
 | 
			
		||||
 | 
			
		||||
import static com.google.common.truth.Truth.assertThat;
 | 
			
		||||
 | 
			
		||||
import static org.mockito.Mockito.spy;
 | 
			
		||||
 | 
			
		||||
import android.app.settings.SettingsEnums;
 | 
			
		||||
import android.os.Flags;
 | 
			
		||||
import android.platform.test.flag.junit.SetFlagsRule;
 | 
			
		||||
 | 
			
		||||
import androidx.test.annotation.UiThreadTest;
 | 
			
		||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
 | 
			
		||||
 | 
			
		||||
import org.junit.Rule;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
 | 
			
		||||
@RunWith(AndroidJUnit4.class)
 | 
			
		||||
public class PrivateSpaceDeleteFragmentTest {
 | 
			
		||||
    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 | 
			
		||||
    private PrivateSpaceDeleteFragment mFragment;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    @UiThreadTest
 | 
			
		||||
    public void verifyMetricsConstant() {
 | 
			
		||||
        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
 | 
			
		||||
        mFragment = spy(new PrivateSpaceDeleteFragment());
 | 
			
		||||
        assertThat(mFragment.getMetricsCategory()).isEqualTo(SettingsEnums.PRIVATE_SPACE_SETTINGS);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,132 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2024 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.privatespace.delete;
 | 
			
		||||
 | 
			
		||||
import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_INTERNAL;
 | 
			
		||||
 | 
			
		||||
import static com.google.common.truth.Truth.assertThat;
 | 
			
		||||
 | 
			
		||||
import static org.mockito.Mockito.doNothing;
 | 
			
		||||
import static org.mockito.Mockito.doReturn;
 | 
			
		||||
import static org.mockito.Mockito.spy;
 | 
			
		||||
import static org.mockito.Mockito.verify;
 | 
			
		||||
 | 
			
		||||
import android.app.settings.SettingsEnums;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.os.Flags;
 | 
			
		||||
import android.platform.test.flag.junit.SetFlagsRule;
 | 
			
		||||
 | 
			
		||||
import androidx.test.annotation.UiThreadTest;
 | 
			
		||||
import androidx.test.core.app.ApplicationProvider;
 | 
			
		||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
 | 
			
		||||
 | 
			
		||||
import com.android.settings.privatespace.PrivateSpaceMaintainer;
 | 
			
		||||
 | 
			
		||||
import org.junit.After;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Rule;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.MockitoAnnotations;
 | 
			
		||||
 | 
			
		||||
@RunWith(AndroidJUnit4.class)
 | 
			
		||||
public class PrivateSpaceDeletionProgressFragmentTest {
 | 
			
		||||
    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 | 
			
		||||
    private Context mContext;
 | 
			
		||||
    private PrivateSpaceDeletionProgressFragment mFragment;
 | 
			
		||||
    private PrivateSpaceMaintainer mPrivateSpaceMaintainer;
 | 
			
		||||
    @Mock private PrivateSpaceMaintainer mPrivateSpaceMaintainerMock;
 | 
			
		||||
 | 
			
		||||
    @UiThreadTest
 | 
			
		||||
    @Before
 | 
			
		||||
    public void setup() {
 | 
			
		||||
        MockitoAnnotations.initMocks(this);
 | 
			
		||||
        mContext = ApplicationProvider.getApplicationContext();
 | 
			
		||||
        mFragment = new PrivateSpaceDeletionProgressFragment();
 | 
			
		||||
        PrivateSpaceDeletionProgressFragment.Injector injector =
 | 
			
		||||
                new PrivateSpaceDeletionProgressFragment.Injector() {
 | 
			
		||||
                    @Override
 | 
			
		||||
                    public PrivateSpaceMaintainer injectPrivateSpaceMaintainer(Context context) {
 | 
			
		||||
                        return mPrivateSpaceMaintainer;
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
        mPrivateSpaceMaintainer = PrivateSpaceMaintainer.getInstance(mContext);
 | 
			
		||||
        mFragment.setPrivateSpaceMaintainer(injector);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @After
 | 
			
		||||
    public void tearDown() {
 | 
			
		||||
        mPrivateSpaceMaintainer.deletePrivateSpace();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    @UiThreadTest
 | 
			
		||||
    public void verifyMetricsConstant() {
 | 
			
		||||
        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
 | 
			
		||||
        assertThat(mFragment.getMetricsCategory()).isEqualTo(SettingsEnums.PRIVATE_SPACE_SETTINGS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Tests that deletePrivateSpace() deletes the private space. */
 | 
			
		||||
    @Test
 | 
			
		||||
    @UiThreadTest
 | 
			
		||||
    public void deletePrivateSpace_deletesPS() {
 | 
			
		||||
        PrivateSpaceDeletionProgressFragment spyFragment = spy(mFragment);
 | 
			
		||||
        doNothing().when(spyFragment).showSuccessfulDeletionToast();
 | 
			
		||||
        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
 | 
			
		||||
 | 
			
		||||
        mPrivateSpaceMaintainer.createPrivateSpace();
 | 
			
		||||
        spyFragment.deletePrivateSpace();
 | 
			
		||||
        assertThat(mPrivateSpaceMaintainer.doesPrivateSpaceExist()).isFalse();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Tests that on deletion of the private space relevant toast is shown. */
 | 
			
		||||
    @Test
 | 
			
		||||
    @UiThreadTest
 | 
			
		||||
    public void deletePrivateSpace_onDeletion_showsDeletedToast() {
 | 
			
		||||
        PrivateSpaceDeletionProgressFragment spyFragment = spy(mFragment);
 | 
			
		||||
        doNothing().when(spyFragment).showSuccessfulDeletionToast();
 | 
			
		||||
        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
 | 
			
		||||
 | 
			
		||||
        mPrivateSpaceMaintainer.createPrivateSpace();
 | 
			
		||||
        spyFragment.deletePrivateSpace();
 | 
			
		||||
        verify(spyFragment).showSuccessfulDeletionToast();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Tests that on failing to delete the private space relevant toast is shown. */
 | 
			
		||||
    @Test
 | 
			
		||||
    @UiThreadTest
 | 
			
		||||
    public void deletePrivateSpace_onDeletionError_showsDeletionFailedToast() {
 | 
			
		||||
        PrivateSpaceDeletionProgressFragment spyFragment =
 | 
			
		||||
                spy(new PrivateSpaceDeletionProgressFragment());
 | 
			
		||||
        PrivateSpaceDeletionProgressFragment.Injector injector =
 | 
			
		||||
                new PrivateSpaceDeletionProgressFragment.Injector() {
 | 
			
		||||
                    @Override
 | 
			
		||||
                    PrivateSpaceMaintainer injectPrivateSpaceMaintainer(Context context) {
 | 
			
		||||
                        return mPrivateSpaceMaintainerMock;
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
        spyFragment.setPrivateSpaceMaintainer(injector);
 | 
			
		||||
        doReturn(DELETE_PS_ERROR_INTERNAL).when(mPrivateSpaceMaintainerMock).deletePrivateSpace();
 | 
			
		||||
        doNothing().when(spyFragment).showDeletionInternalErrorToast();
 | 
			
		||||
        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
 | 
			
		||||
 | 
			
		||||
        spyFragment.deletePrivateSpace();
 | 
			
		||||
 | 
			
		||||
        verify(spyFragment).showDeletionInternalErrorToast();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user