Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 606ff9b7 authored by Doris Ling's avatar Doris Ling Committed by Android (Google) Code Review
Browse files

Merge "Move clear instant app dialog logic out of AppInfoDashboardFragment."

parents f350fa87 f176175f
Loading
Loading
Loading
Loading
+3 −50
Original line number Diff line number Diff line
@@ -19,9 +19,6 @@ package com.android.settings.applications.appinfo;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -95,10 +92,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
    static final int LOADER_STORAGE = 3;
    static final int LOADER_BATTERY = 4;

    // Dialog identifiers used in showDialog
    private static final int DLG_BASE = 0;
    static final int DLG_CLEAR_INSTANT_APP = DLG_BASE + 1;

    public static final String ARG_PACKAGE_NAME = "package";
    public static final String ARG_PACKAGE_UID = "uid";

@@ -419,7 +412,9 @@ public class AppInfoDashboardFragment extends DashboardFragment
        for (Callback callback : mCallbacks) {
            callback.refreshUi();
        }
        if (mAppButtonsPreferenceController.isAvailable()) {
            mAppButtonsPreferenceController.refreshUi();
        }

        if (!mInitialized) {
            // First time init: are we displaying an uninstalled app?
@@ -447,11 +442,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
        return true;
    }

    @VisibleForTesting
    AlertDialog createDialog(int id, int errorCode) {
        return mInstantAppButtonPreferenceController.createDialog(id);
    }

    private void uninstallPkg(String packageName, boolean allUsers, boolean andDisable) {
        stopListeningToPackageRemove();
        // Create new intent to launch Uninstaller activity
@@ -561,12 +551,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
        mFinishing = true;
    }

    void showDialogInner(int id, int moveErrorCode) {
        final DialogFragment newFragment = MyAlertDialogFragment.newInstance(id, moveErrorCode);
        newFragment.setTargetFragment(this, 0);
        newFragment.show(getFragmentManager(), "dialog " + id);
    }

    @Override
    public void onRunningStateChanged(boolean running) {
        // No op.
@@ -604,37 +588,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
        }
    }

    public static class MyAlertDialogFragment extends InstrumentedDialogFragment {

        private static final String ARG_ID = "id";

        @Override
        public int getMetricsCategory() {
            return MetricsEvent.DIALOG_APP_INFO_ACTION;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final int id = getArguments().getInt(ARG_ID);
            final int errorCode = getArguments().getInt("moveError");
            final Dialog dialog =
                    ((AppInfoDashboardFragment) getTargetFragment()).createDialog(id, errorCode);
            if (dialog == null) {
                throw new IllegalArgumentException("unknown id " + id);
            }
            return dialog;
        }

        public static MyAlertDialogFragment newInstance(int id, int errorCode) {
            final MyAlertDialogFragment dialogFragment = new MyAlertDialogFragment();
            final Bundle args = new Bundle();
            args.putInt(ARG_ID, id);
            args.putInt("moveError", errorCode);
            dialogFragment.setArguments(args);
            return dialogFragment;
        }
    }

    @VisibleForTesting
    void startListeningToPackageRemove() {
        if (mListeningToPackageRemove) {
+15 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.appinfo;

import android.app.AlertDialog;
+80 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.appinfo;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.overlay.FeatureFactory;

/**
 * Fragment to show the dialog for clearing the instant app.
 */
public class InstantAppButtonDialogFragment extends InstrumentedDialogFragment implements
        DialogInterface.OnClickListener {

    private static final String ARG_PACKAGE_NAME = "packageName";

    private String mPackageName;

    public static InstantAppButtonDialogFragment newInstance(String packageName) {
        final InstantAppButtonDialogFragment dialogFragment = new InstantAppButtonDialogFragment();
        final Bundle args = new Bundle(1);
        args.putString(ARG_PACKAGE_NAME, packageName);
        dialogFragment.setArguments(args);
        return dialogFragment;
    }

    @Override
    public int getMetricsCategory() {
        return MetricsEvent.DIALOG_APP_INFO_ACTION;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Bundle arguments = getArguments();
        mPackageName = arguments.getString(ARG_PACKAGE_NAME);
        return createDialog();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        final Context context = getContext();
        final PackageManager packageManager = context.getPackageManager();
        FeatureFactory.getFactory(context).getMetricsFeatureProvider()
            .action(context, MetricsEvent.ACTION_SETTINGS_CLEAR_INSTANT_APP, mPackageName);
        packageManager.deletePackageAsUser(mPackageName, null, 0, UserHandle.myUserId());
    }

    private AlertDialog createDialog() {
        AlertDialog confirmDialog = new AlertDialog.Builder(getContext())
            .setPositiveButton(R.string.clear_instant_app_data, this)
            .setNegativeButton(R.string.cancel, null)
            .setTitle(R.string.clear_instant_app_data)
            .setMessage(R.string.clear_instant_app_confirmation)
            .create();
        return confirmDialog;
    }

}
+10 −32
Original line number Diff line number Diff line
@@ -16,15 +16,13 @@

package com.android.settings.applications.appinfo;

import android.app.AlertDialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;

import androidx.preference.PreferenceScreen;
import android.text.TextUtils;
@@ -34,12 +32,10 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.Button;

import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.AppStoreUtil;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -50,15 +46,13 @@ import com.android.settingslib.core.lifecycle.events.OnPrepareOptionsMenu;
import java.util.List;

public class InstantAppButtonsPreferenceController extends BasePreferenceController implements
        LifecycleObserver, OnCreateOptionsMenu, OnPrepareOptionsMenu, OnOptionsItemSelected,
        DialogInterface.OnClickListener {
        LifecycleObserver, OnCreateOptionsMenu, OnPrepareOptionsMenu, OnOptionsItemSelected {

    private static final String KEY_INSTANT_APP_BUTTONS = "instant_app_buttons";
    private static final String META_DATA_DEFAULT_URI = "default-url";

    private final AppInfoDashboardFragment mParent;
    private final String mPackageName;
    private final PackageManager mPackageManager;
    private String mLaunchUri;
    private LayoutPreference mPreference;
    private MenuItem mInstallMenu;
@@ -68,7 +62,6 @@ public class InstantAppButtonsPreferenceController extends BasePreferenceControl
        super(context, KEY_INSTANT_APP_BUTTONS);
        mParent = parent;
        mPackageName = packageName;
        mPackageManager = context.getPackageManager();
        mLaunchUri = getDefaultLaunchUri();
        if (lifecycle != null) {
            lifecycle.addObserver(this);
@@ -118,27 +111,6 @@ public class InstantAppButtonsPreferenceController extends BasePreferenceControl
        }
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        FeatureFactory.getFactory(mContext).getMetricsFeatureProvider()
            .action(mContext, MetricsEvent.ACTION_SETTINGS_CLEAR_INSTANT_APP, mPackageName);
        mPackageManager.deletePackageAsUser(
            mPackageName, null, 0, UserHandle.myUserId());
    }

    AlertDialog createDialog(int id) {
        if (id == AppInfoDashboardFragment.DLG_CLEAR_INSTANT_APP) {
            AlertDialog confirmDialog = new AlertDialog.Builder(mContext)
                .setPositiveButton(R.string.clear_instant_app_data, this)
                .setNegativeButton(R.string.cancel, null)
                .setTitle(R.string.clear_instant_app_data)
                .setMessage(mContext.getString(R.string.clear_instant_app_confirmation))
                .create();
            return confirmDialog;
        }
        return null;
    }

    private void initButtons(View view) {
        final Button installButton = view.findViewById(R.id.install);
        final Button clearDataButton = view.findViewById(R.id.clear_data);
@@ -160,8 +132,14 @@ public class InstantAppButtonsPreferenceController extends BasePreferenceControl
                installButton.setEnabled(false);
            }
        }
        clearDataButton.setOnClickListener(
            v -> mParent.showDialogInner(mParent.DLG_CLEAR_INSTANT_APP, 0));
        clearDataButton.setOnClickListener(v -> showDialog());
    }

    private void showDialog() {
        final DialogFragment newFragment =
            InstantAppButtonDialogFragment.newInstance(mPackageName);
        newFragment.setTargetFragment(mParent, 0);
        newFragment.show(mParent.getFragmentManager(), KEY_INSTANT_APP_BUTTONS);
    }

    private String getDefaultLaunchUri() {
+87 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.appinfo;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.shadows.ShadowDialog;
import org.robolectric.util.FragmentTestUtil;

@RunWith(SettingsRobolectricTestRunner.class)
public class InstantAppButtonDialogFragmentTest {

    private static final String TEST_PACKAGE = "testPackage";

    private InstantAppButtonDialogFragment mFragment;
    private Context mContext;

    @Before
    public void setUp() {
        mContext = spy(RuntimeEnvironment.application);
        mFragment = spy(InstantAppButtonDialogFragment.newInstance(TEST_PACKAGE));
        doReturn(mContext).when(mFragment).getContext();
    }

    @Test
    public void onClick_shouldDeleteApp() {
        final PackageManager packageManager = mock(PackageManager.class);
        when(mContext.getPackageManager()).thenReturn(packageManager);
        FragmentTestUtil.startFragment(mFragment);

        mFragment.onClick(null /* dialog */, 0  /* which */);

        verify(packageManager)
            .deletePackageAsUser(eq(TEST_PACKAGE), any(), anyInt(), anyInt());
    }

    @Test
    public void onCreateDialog_clearAppDialog_shouldShowClearAppDataConfirmation() {
        FragmentTestUtil.startFragment(mFragment);

        final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
        assertThat(dialog).isNotNull();
        final ShadowAlertDialog shadowDialog = shadowOf(dialog);

        assertThat(shadowDialog.getMessage()).isEqualTo(
                mContext.getString(R.string.clear_instant_app_confirmation));
        assertThat(shadowDialog.getTitle()).isEqualTo(
                mContext.getString(R.string.clear_instant_app_data));
        assertThat(dialog.getButton(DialogInterface.BUTTON_POSITIVE).getText()).isEqualTo(
                mContext.getString(R.string.clear_instant_app_data));
        assertThat(dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getText()).isEqualTo(
                mContext.getString(R.string.cancel));
    }
}
Loading