Provide a way to Magnification settings via intent

Framework needs a way to launch magnification settings.

bug: 168635084
Test: adb shell am start -a \
     "android.settings.ACCESSIBILITY_DETAILS_SETTINGS"  \
     --es android.intent.extra.COMPONENT_NAME  \
     "com.android.server.accessibility/Magnification"
     AccessibilityDetailsSettingsFragmentTest
Change-Id: Iafb5ad4802a52e4bf3c443af99cd27ef0da0ea29
diff --git a/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java b/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java
index e91f2a2..58cdb72 100644
--- a/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.accessibility;
 
+import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
+
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
@@ -30,6 +32,9 @@
 import android.util.Log;
 import android.view.accessibility.AccessibilityManager;
 
+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;
@@ -37,6 +42,7 @@
 import com.android.settingslib.accessibility.AccessibilityUtils;
 
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 public class AccessibilityDetailsSettingsFragment extends InstrumentedFragment {
@@ -61,44 +67,77 @@
             return;
         }
 
-        // In case the A11yServiceInfo doesn't exist, go to ally services list.
         final ComponentName componentName = ComponentName.unflattenFromString(extraComponentName);
+        if (openSystemAccessibilitySettingsAndFinish(componentName)) {
+            return;
+        }
+
+        if (openAccessibilityDetailsSettingsAndFinish(componentName)) {
+            return;
+        }
+        // Fall back to open accessibility services list.
+        openAccessibilitySettingsAndFinish();
+    }
+
+    private boolean openSystemAccessibilitySettingsAndFinish(
+            @Nullable ComponentName componentName) {
+        final LaunchFragmentArguments launchArguments =
+                getSystemAccessibilitySettingsLaunchArguments(componentName);
+        if (launchArguments == null) {
+            return false;
+        }
+        openSubSettings(launchArguments.mDestination, launchArguments.mArguments);
+        finish();
+        return true;
+    }
+
+    @Nullable
+    private LaunchFragmentArguments getSystemAccessibilitySettingsLaunchArguments(
+            @Nullable ComponentName componentName) {
+        if (MAGNIFICATION_COMPONENT_NAME.equals(componentName)) {
+            final String destination = ToggleScreenMagnificationPreferenceFragment.class.getName();
+            final Bundle arguments = new Bundle();
+            MagnificationGesturesPreferenceController.populateMagnificationGesturesPreferenceExtras(
+                    arguments, getContext());
+            return new LaunchFragmentArguments(destination, arguments);
+        }
+        return null;
+    }
+
+
+    private void openAccessibilitySettingsAndFinish() {
+        openSubSettings(AccessibilitySettings.class.getName(), /* arguments= */ null);
+        finish();
+    }
+
+    private boolean openAccessibilityDetailsSettingsAndFinish(
+            @Nullable ComponentName componentName) {
+        // In case the A11yServiceInfo doesn't exist, go to ally services list.
         final AccessibilityServiceInfo info = getAccessibilityServiceInfo(componentName);
         if (info == null) {
-            Log.w(TAG, "Open accessibility services list due to invalid component name.");
-            openAccessibilitySettingsAndFinish();
-            return;
+            Log.w(TAG, "openAccessibilityDetailsSettingsAndFinish : invalid component name.");
+            return false;
         }
 
         // In case this accessibility service isn't permitted, go to a11y services list.
         if (!isServiceAllowed(componentName.getPackageName())) {
             Log.w(TAG,
-                    "Open accessibility services list due to target accessibility service is "
+                    "openAccessibilityDetailsSettingsAndFinish: target accessibility service is"
                             + "prohibited by Device Admin.");
-            openAccessibilitySettingsAndFinish();
-            return;
+            return false;
         }
-
-        openAccessibilityDetailsSettingsAndFinish(buildArguments(info));
-    }
-
-    @VisibleForTesting
-    void openAccessibilitySettingsAndFinish() {
-        new SubSettingLauncher(getActivity())
-                .setDestination(AccessibilitySettings.class.getName())
-                .setSourceMetricsCategory(getMetricsCategory())
-                .launch();
+        openSubSettings(ToggleAccessibilityServicePreferenceFragment.class.getName(),
+                buildArguments(info));
         finish();
+        return true;
     }
 
-    @VisibleForTesting
-    void openAccessibilityDetailsSettingsAndFinish(Bundle arguments) {
+    private void openSubSettings(@NonNull String destination, @Nullable Bundle arguments) {
         new SubSettingLauncher(getActivity())
-                .setDestination(ToggleAccessibilityServicePreferenceFragment.class.getName())
+                .setDestination(destination)
                 .setSourceMetricsCategory(getMetricsCategory())
                 .setArguments(arguments)
                 .launch();
-        finish();
     }
 
     @VisibleForTesting
@@ -175,4 +214,13 @@
         }
         activity.finish();
     }
+
+    private static class LaunchFragmentArguments {
+        final String mDestination;
+        final Bundle mArguments;
+        LaunchFragmentArguments(@NonNull String destination, @Nullable Bundle arguments) {
+            mDestination = Objects.requireNonNull(destination);
+            mArguments = arguments;
+        }
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java
index 9ad00eb..a04f0cf 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java
@@ -16,6 +16,10 @@
 
 package com.android.settings.accessibility;
 
+import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
+
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
@@ -33,11 +37,14 @@
 
 import androidx.fragment.app.FragmentActivity;
 
+import com.android.settings.SettingsActivity;
 import com.android.settings.testutils.shadow.ShadowFragment;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
@@ -61,6 +68,8 @@
     private Context mContext;
     private AccessibilityDetailsSettingsFragment mFragment;
     private ShadowAccessibilityManager mShadowAccessibilityManager;
+    @Captor
+    private ArgumentCaptor<Intent> mIntentArgumentCaptor;
     @Mock private FragmentActivity mActivity;
 
     @Before
@@ -76,39 +85,43 @@
     }
 
     @Test
-    public void onCreate_hasValidExtraComponentName_shouldOpenAccessibilityDetailsSettings() {
+    public void onCreate_hasValidExtraComponentName_launchExpectedFragmentAndFinish() {
         final Intent intent = new Intent();
         intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
         doReturn(intent).when(mActivity).getIntent();
 
         mFragment.onCreate(Bundle.EMPTY);
 
-        verify(mFragment).openAccessibilityDetailsSettingsAndFinish(any());
+        assertStartActivityWithExpectedFragment(mActivity,
+                ToggleAccessibilityServicePreferenceFragment.class.getName());
+        verify(mActivity).finish();
     }
 
     @Test
-    public void onCreate_hasInvalidExtraComponentName_shouldOpenAccessibilityServicesList() {
+    public void onCreate_hasInvalidExtraComponentName_launchAccessibilitySettingsAndFinish() {
         final Intent intent = new Intent();
         intent.putExtra(Intent.EXTRA_COMPONENT_NAME, PACKAGE_NAME + "/.service");
         doReturn(intent).when(mActivity).getIntent();
 
         mFragment.onCreate(Bundle.EMPTY);
 
-        verify(mFragment).openAccessibilitySettingsAndFinish();
+        assertStartActivityWithExpectedFragment(mActivity, AccessibilitySettings.class.getName());
+        verify(mActivity).finish();
     }
 
     @Test
-    public void onCreate_hasNoExtraComponentName_shouldOpenAccessibilityServicesList() {
+    public void onCreate_hasNoExtraComponentName_launchAccessibilitySettingsAndFinish() {
         final Intent intent = new Intent();
         doReturn(intent).when(mActivity).getIntent();
 
         mFragment.onCreate(Bundle.EMPTY);
 
-        verify(mFragment).openAccessibilitySettingsAndFinish();
+        assertStartActivityWithExpectedFragment(mActivity, AccessibilitySettings.class.getName());
+        verify(mActivity).finish();
     }
 
     @Test
-    public void onCreate_extraComponentNameIsDisallowed_shouldOpenAccessibilityServicesList() {
+    public void onCreate_extraComponentNameIsDisallowed_launchAccessibilitySettingsAndFinish() {
         final Intent intent = new Intent();
         intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
         doReturn(intent).when(mActivity).getIntent();
@@ -116,7 +129,23 @@
 
         mFragment.onCreate(Bundle.EMPTY);
 
-        verify(mFragment).openAccessibilitySettingsAndFinish();
+        assertStartActivityWithExpectedFragment(mActivity, AccessibilitySettings.class.getName());
+        verify(mActivity).finish();
+    }
+
+    @Test
+    public void onCreate_magnificationComponentName_launchMagnificationFragmentAndFinish() {
+        final Intent intent = new Intent();
+        intent.putExtra(Intent.EXTRA_COMPONENT_NAME,
+                MAGNIFICATION_COMPONENT_NAME.flattenToString());
+        doReturn(intent).when(mActivity).getIntent();
+
+        mFragment.onCreate(Bundle.EMPTY);
+
+
+        assertStartActivityWithExpectedFragment(mActivity,
+                ToggleScreenMagnificationPreferenceFragment.class.getName());
+        verify(mActivity).finish();
     }
 
     private AccessibilityServiceInfo getMockAccessibilityServiceInfo() {
@@ -148,4 +177,11 @@
         infoList.add(getMockAccessibilityServiceInfo());
         return infoList;
     }
+
+    private void assertStartActivityWithExpectedFragment(Context mockContext, String fragmentName) {
+        verify(mockContext).startActivity(mIntentArgumentCaptor.capture());
+        assertThat(mIntentArgumentCaptor.getValue()
+                .getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
+                .isEqualTo(fragmentName);
+    }
 }