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

Commit 4ac18324 authored by Chris Antol's avatar Chris Antol Committed by Android (Google) Code Review
Browse files

Merge "Checks cross user permission before handling intent" into main

parents 78e191a6 d3b3edd4
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.applications;

import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;

import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
@@ -39,6 +40,7 @@ import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
@@ -134,6 +136,11 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
                mPackageName = intent.getData().getSchemeSpecificPart();
            }
        }
        if (!hasInteractAcrossUsersPermission()) {
            Log.w(TAG, "Intent not valid.");
            finish();
            return "";
        }
        if (intent != null && intent.hasExtra(Intent.EXTRA_USER_HANDLE)) {
            mUserId = ((UserHandle) intent.getParcelableExtra(
                    Intent.EXTRA_USER_HANDLE)).getIdentifier();
@@ -163,6 +170,28 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
        return mPackageName;
    }

    @VisibleForTesting
    protected boolean hasInteractAcrossUsersPermission() {
        Activity activity = getActivity();
        if (!(activity instanceof SettingsActivity)) {
            return false;
        }
        final String callingPackageName =
                ((SettingsActivity) activity).getInitialCallingPackage();

        if (TextUtils.isEmpty(callingPackageName)) {
            Log.w(TAG, "Not able to get calling package name for permission check");
            return false;
        }
        if (mPm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingPackageName)
                != PackageManager.PERMISSION_GRANTED) {
            Log.w(TAG, "Package " + callingPackageName + " does not have required permission "
                    + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
            return false;
        }
        return true;
    }

    protected void setIntentAndFinish(boolean appChanged) {
        Log.i(TAG, "appChanged=" + appChanged);
        Intent intent = new Intent();
+38 −0
Original line number Diff line number Diff line
@@ -171,6 +171,32 @@ public class AppInfoWithHeaderTest {
        assertThat(mAppInfoWithHeader.mAppEntry).isNotNull();
    }

    @Test
    public void noCrossUserPermission_retrieveAppEntry_fail()
            throws PackageManager.NameNotFoundException {
        TestFragmentWithoutPermission testFragmentWithoutPermission =
                new TestFragmentWithoutPermission();
        final int userId = 1002;
        final String packageName = "com.android.settings";

        testFragmentWithoutPermission.mIntent.putExtra(Intent.EXTRA_USER_HANDLE,
                new UserHandle(userId));
        testFragmentWithoutPermission.mIntent.setData(Uri.fromParts("package",
                packageName, null));
        final ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
        entry.info = new ApplicationInfo();
        entry.info.packageName = packageName;

        when(testFragmentWithoutPermission.mState.getEntry(packageName, userId)).thenReturn(entry);
        when(testFragmentWithoutPermission.mPm.getPackageInfoAsUser(eq(entry.info.packageName),
                any(), eq(userId))).thenReturn(
                testFragmentWithoutPermission.mPackageInfo);

        testFragmentWithoutPermission.retrieveAppEntry();

        assertThat(testFragmentWithoutPermission.mAppEntry).isNull();
    }

    public static class TestFragment extends AppInfoWithHeader {

        PreferenceManager mManager;
@@ -223,6 +249,11 @@ public class AppInfoWithHeaderTest {
            return mShadowContext;
        }

        @Override
        protected boolean hasInteractAcrossUsersPermission() {
            return true;
        }

        @Override
        protected void onPackageRemoved() {
            mPackageRemovedCalled = true;
@@ -233,4 +264,11 @@ public class AppInfoWithHeaderTest {
            return mIntent;
        }
    }

    private static final class TestFragmentWithoutPermission extends TestFragment {
        @Override
        protected boolean hasInteractAcrossUsersPermission() {
            return false;
        }
    }
}
+22 −9
Original line number Diff line number Diff line
@@ -39,23 +39,26 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.Manifest;
import android.app.Application;
import android.app.IActivityManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;

import androidx.fragment.app.testing.EmptyFragmentActivity;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.rules.ActivityScenarioRule;

import com.android.settings.SettingsActivity;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
@@ -71,14 +74,14 @@ import org.robolectric.annotation.Config;
@Config(shadows = {ShadowActivityManager.class, ShadowFragment.class})
public class UserAspectRatioDetailsTest {

    @Rule
    public ActivityScenarioRule<EmptyFragmentActivity> rule =
            new ActivityScenarioRule<>(EmptyFragmentActivity.class);

    @Mock
    private UserAspectRatioManager mUserAspectRatioManager;
    @Mock
    private IActivityManager mAm;
    @Mock
    private PackageManager mPackageManager;
    @Mock
    private SettingsActivity mSettingsActivity;

    private RadioWithImagePreference mRadioButtonPref;
    private Context mContext;
@@ -93,6 +96,12 @@ public class UserAspectRatioDetailsTest {
        mFragment = spy(new UserAspectRatioDetails());
        when(mFragment.getContext()).thenReturn(mContext);
        when(mFragment.getAspectRatioManager()).thenReturn(mUserAspectRatioManager);
        when(mFragment.getActivity()).thenReturn(mSettingsActivity);
        when(mSettingsActivity.getApplication()).thenReturn((Application) mContext);
        when(mSettingsActivity.getInitialCallingPackage()).thenReturn("test.package");
        when(mSettingsActivity.getPackageManager()).thenReturn(mPackageManager);
        when(mPackageManager.checkPermission(eq(Manifest.permission.INTERACT_ACROSS_USERS_FULL),
                any())).thenReturn(PackageManager.PERMISSION_GRANTED);
        when(mUserAspectRatioManager.isOverrideToFullscreenEnabled(anyString(), anyInt()))
                .thenReturn(false);
        ShadowActivityManager.setService(mAm);
@@ -111,8 +120,10 @@ public class UserAspectRatioDetailsTest {
                .getUserMinAspectRatioOrder(USER_MIN_ASPECT_RATIO_FULLSCREEN);
        doReturn(2).when(mUserAspectRatioManager)
                .getUserMinAspectRatioOrder(USER_MIN_ASPECT_RATIO_UNSET);
        rule.getScenario().onActivity(a -> doReturn(a).when(mFragment).getActivity());
        final Bundle args = new Bundle();
        Intent intent = new Intent();
        intent.putExtra(Intent.EXTRA_USER_HANDLE, new UserHandle(0));
        args.putParcelable("intent", intent);
        args.putString(ARG_PACKAGE_NAME, anyString());
        mFragment.setArguments(args);
        mFragment.onCreate(Bundle.EMPTY);
@@ -196,8 +207,10 @@ public class UserAspectRatioDetailsTest {
        doReturn(true).when(mUserAspectRatioManager)
                .hasAspectRatioOption(anyInt(), anyString());

        rule.getScenario().onActivity(a -> doReturn(a).when(mFragment).getActivity());
        final Bundle args = new Bundle();
        Intent intent = new Intent();
        intent.putExtra(Intent.EXTRA_USER_HANDLE, new UserHandle(0));
        args.putParcelable("intent", intent);
        args.putString(ARG_PACKAGE_NAME, anyString());
        mFragment.setArguments(args);
        mFragment.onCreate(Bundle.EMPTY);