diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8411d31ddbd..d52b0ceda6d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3181,7 +3181,7 @@ - - - + android:title="@string/quick_settings_developer_tiles" + android:fragment="com.android.settings.development.qstile.DevelopmentTileConfigFragment" /> diff --git a/src/com/android/settings/development/qstile/DevelopmentTileConfigFragment.java b/src/com/android/settings/development/qstile/DevelopmentTileConfigFragment.java new file mode 100644 index 00000000000..c822de007e9 --- /dev/null +++ b/src/com/android/settings/development/qstile/DevelopmentTileConfigFragment.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 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.development.qstile; + +import android.content.Context; + +import com.android.internal.logging.nano.MetricsProto; +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settingslib.core.AbstractPreferenceController; + +import java.util.ArrayList; +import java.util.List; + +public class DevelopmentTileConfigFragment extends DashboardFragment { + private static final String TAG = "DevelopmentTileConfig"; + + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.placeholder_prefs; + } + + @Override + protected List getPreferenceControllers(Context context) { + final List controllers = new ArrayList<>(); + controllers.add(new DevelopmentTilePreferenceController(context)); + return controllers; + } + + @Override + public int getMetricsCategory() { + return MetricsProto.MetricsEvent.DEVELOPMENT_QS_TILE_CONFIG; + } +} diff --git a/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java b/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java new file mode 100644 index 00000000000..083a7195c77 --- /dev/null +++ b/src/com/android/settings/development/qstile/DevelopmentTilePreferenceController.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2017 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.development.qstile; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.service.quicksettings.TileService; +import android.support.v14.preference.SwitchPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settingslib.core.AbstractPreferenceController; + +import java.util.List; + +public class DevelopmentTilePreferenceController extends AbstractPreferenceController { + + private final OnChangeHandler mOnChangeHandler; + private final PackageManager mPackageManager; + + public DevelopmentTilePreferenceController(Context context) { + super(context); + mOnChangeHandler = new OnChangeHandler(context); + mPackageManager = context.getPackageManager(); + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public String getPreferenceKey() { + return null; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + Context context = screen.getContext(); + Intent intent = new Intent(TileService.ACTION_QS_TILE) + .setPackage(context.getPackageName()); + final List resolveInfos = mPackageManager.queryIntentServices(intent, + PackageManager.MATCH_DISABLED_COMPONENTS); + for (ResolveInfo info : resolveInfos) { + ServiceInfo sInfo = info.serviceInfo; + final int enabledSetting = mPackageManager.getComponentEnabledSetting( + new ComponentName(sInfo.packageName, sInfo.name)); + boolean checked = enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED + || ((enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) + && sInfo.enabled); + + SwitchPreference preference = new SwitchPreference(context); + preference.setTitle(sInfo.loadLabel(mPackageManager)); + preference.setIcon(sInfo.icon); + preference.setKey(sInfo.name); + preference.setChecked(checked); + preference.setOnPreferenceChangeListener(mOnChangeHandler); + screen.addPreference(preference); + } + } + + private static class OnChangeHandler implements Preference.OnPreferenceChangeListener { + + private final Context mContext; + private final PackageManager mPackageManager; + + public OnChangeHandler(Context context) { + mContext = context; + mPackageManager = context.getPackageManager(); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + ComponentName cn = new ComponentName( + mContext.getPackageName(), preference.getKey()); + mPackageManager.setComponentEnabledSetting(cn, (Boolean) newValue + ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED + : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + return true; + } + } +} diff --git a/src/com/android/settings/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java similarity index 98% rename from src/com/android/settings/qstile/DevelopmentTiles.java rename to src/com/android/settings/development/qstile/DevelopmentTiles.java index f05977b1c7f..bc3fcb5af77 100644 --- a/src/com/android/settings/qstile/DevelopmentTiles.java +++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java @@ -14,7 +14,7 @@ * the License. */ -package com.android.settings.qstile; +package com.android.settings.development.qstile; import android.os.RemoteException; import android.os.SystemProperties; diff --git a/src/com/android/settings/qstile/DevelopmentTileConfigActivity.java b/src/com/android/settings/qstile/DevelopmentTileConfigActivity.java deleted file mode 100644 index 5968d7a0896..00000000000 --- a/src/com/android/settings/qstile/DevelopmentTileConfigActivity.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2016 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.qstile; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.os.Bundle; -import android.service.quicksettings.TileService; -import android.support.v14.preference.SwitchPreference; -import android.support.v7.preference.Preference; - -import com.android.settings.SettingsActivity; -import com.android.settings.SettingsPreferenceFragment; -import com.android.settings.core.instrumentation.Instrumentable; - -public class DevelopmentTileConfigActivity extends SettingsActivity { - - @Override - public Intent getIntent() { - Intent modIntent = new Intent(super.getIntent()) - .putExtra(EXTRA_SHOW_FRAGMENT, DevelopmentTileConfigFragment.class.getName()) - .putExtra(EXTRA_HIDE_DRAWER, true); - return modIntent; - } - - @Override - protected boolean isValidFragment(String fragmentName) { - return (DevelopmentTileConfigFragment.class.getName().equals(fragmentName)); - } - - public static class DevelopmentTileConfigFragment extends SettingsPreferenceFragment - implements Preference.OnPreferenceChangeListener { - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - Context context = getPrefContext(); - setPreferenceScreen(getPreferenceManager().createPreferenceScreen(context)); - getPreferenceScreen().removeAll(); - - Intent intent = new Intent(TileService.ACTION_QS_TILE) - .setPackage(context.getPackageName()); - PackageManager pm = getPackageManager(); - for (ResolveInfo info : - pm.queryIntentServices(intent, PackageManager.MATCH_DISABLED_COMPONENTS)) { - ServiceInfo sInfo = info.serviceInfo; - int enabledSetting = pm.getComponentEnabledSetting( - new ComponentName(sInfo.packageName, sInfo.name)); - boolean checked = enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED - || ((enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) - && sInfo.enabled); - - SwitchPreference preference = new SwitchPreference(context); - preference.setTitle(sInfo.loadLabel(pm)); - preference.setIcon(sInfo.icon); - preference.setKey(sInfo.name); - preference.setChecked(checked); - preference.setPersistent(false); - preference.setOnPreferenceChangeListener(this); - getPreferenceScreen().addPreference(preference); - } - } - - @Override - public int getMetricsCategory() { - return Instrumentable.METRICS_CATEGORY_UNKNOWN; - } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - ComponentName cn = new ComponentName( - getPrefContext().getPackageName(), preference.getKey()); - getPackageManager().setComponentEnabledSetting(cn, (Boolean) newValue - ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED - : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, - PackageManager.DONT_KILL_APP); - return true; - } - } -} \ No newline at end of file diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider index 9b86ced2984..fda5c8a5c70 100644 --- a/tests/robotests/assets/grandfather_not_implementing_index_provider +++ b/tests/robotests/assets/grandfather_not_implementing_index_provider @@ -5,6 +5,7 @@ com.android.settings.accounts.AccountDetailDashboardFragment com.android.settings.fuelgauge.PowerUsageAnomalyDetails com.android.settings.fuelgauge.AdvancedPowerUsageDetail com.android.settings.development.featureflags.FeatureFlagsDashboard +com.android.settings.development.qstile.DevelopmentTileConfigFragment com.android.settings.deviceinfo.StorageProfileFragment com.android.settings.wifi.details.WifiNetworkDetailsFragment com.android.settings.wifi.p2p.WifiP2pSettings diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable index bbb4bb20039..17c8133d435 100644 --- a/tests/robotests/assets/grandfather_not_implementing_indexable +++ b/tests/robotests/assets/grandfather_not_implementing_indexable @@ -72,7 +72,6 @@ com.android.settings.notification.NotificationAccessSettings com.android.settings.notification.ZenModeSettings com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment com.android.settings.localepicker.LocaleListEditor -com.android.settings.qstile.DevelopmentTileConfigActivity$DevelopmentTileConfigFragment com.android.settings.applications.ExternalSourcesDetails com.android.settings.applications.PictureInPictureSettings com.android.settings.applications.PictureInPictureDetails diff --git a/tests/robotests/src/com/android/settings/development/qstile/DevelopmentTilePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/qstile/DevelopmentTilePreferenceControllerTest.java new file mode 100644 index 00000000000..1cdff2092d9 --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/qstile/DevelopmentTilePreferenceControllerTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2017 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.development.qstile; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.service.quicksettings.TileService; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.Shadows; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowPackageManager; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class DevelopmentTilePreferenceControllerTest { + + @Mock + private PreferenceScreen mScreen; + private Context mContext; + private DevelopmentTilePreferenceController mController; + private ShadowPackageManager mShadowPackageManager; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager()); + when(mScreen.getContext()).thenReturn(mContext); + + mController = new DevelopmentTilePreferenceController(mContext); + assertThat(mController.getPreferenceKey()).isNull(); + } + + @Test + public void isAlwaysAvailable() { + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void display_hasTileService_shouldDisplay() { + final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE) + .setPackage(mContext.getPackageName()); + final ResolveInfo info = new ResolveInfo(); + info.serviceInfo = new FakeServiceInfo(); + info.serviceInfo.name = "abc"; + info.serviceInfo.icon = R.drawable.ic_settings_24dp; + info.serviceInfo.packageName = mContext.getPackageName(); + mShadowPackageManager.addResolveInfoForIntent(tileProbe, info); + + mController.displayPreference(mScreen); + + verify(mScreen).addPreference(any(Preference.class)); + } + + public static class FakeServiceInfo extends ServiceInfo { + + public String loadLabel(PackageManager mgr) { + return "hi"; + } + } + +}