Merge "Removing one all-purpose developer tile and replacing it with 4 separate tiles, for individual actions. Also adding a section in Developer Options for enabling these individual tiles."

This commit is contained in:
TreeHugger Robot
2017-02-10 01:11:28 +00:00
committed by Android (Google) Code Review
14 changed files with 423 additions and 504 deletions

View File

@@ -62,7 +62,6 @@ import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.dashboard.SearchResultsSummary;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.qstile.DevelopmentModeTile;
import com.android.settings.search.DynamicIndexableContentMonitor;
import com.android.settings.search2.SearchFeatureProvider;
import com.android.settings.widget.SwitchBar;
@@ -941,9 +940,6 @@ public class SettingsActivity extends SettingsDrawerActivity
Settings.DevelopmentSettingsActivity.DASHBOARD_ALIAS),
showDev, isAdmin);
// Reveal development-only quick settings tiles
setTileEnabled(new ComponentName(this, DevelopmentModeTile.class), showDev);
if (UserHandle.MU_ENABLED && !isAdmin) {
// When on restricted users, disable all extra categories (but only the settings ones).
List<DashboardCategory> categories;

View File

@@ -1,205 +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.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.view.IWindowManager;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.WindowManagerGlobal;
import com.android.internal.app.LocalePicker;
import com.android.settings.DevelopmentSettings;
import java.util.Map;
public class DevelopmentModeTile extends TileService {
static final String SHARED_PREFERENCES_NAME = "development_mode_tile_settings";
private static final String SHOW_TOUCHES_KEY = "show_touches";
private static final String POINTER_LOCATION_KEY = "pointer_location";
private static final String DEBUG_LAYOUT_KEY = "debug_layout";
private static final String FORCE_RTL_LAYOUT_KEY = "force_rtl_layout_all_locales";
private static final String WINDOW_ANIMATION_SCALE_KEY = "window_animation_scale";
private static final String TRANSITION_ANIMATION_SCALE_KEY = "transition_animation_scale";
private static final String ANIMATOR_DURATION_SCALE_KEY = "animator_duration_scale";
private static final String SHOW_HW_SCREEN_UPDATES_KEY = "show_hw_screen_udpates";
private static final String SHOW_HW_LAYERS_UPDATES_KEY = "show_hw_layers_udpates";
private static final String DEBUG_HW_OVERDRAW_KEY = "debug_hw_overdraw";
private static final String TRACK_FRAME_TIME_KEY = "track_frame_time";
private DevModeProperties mProps = new DevModeProperties();
@Override
public void onStartListening() {
super.onStartListening();
refresh();
}
public void refresh() {
mProps.refreshState(this);
getQsTile().setState(mProps.isSet ? (mProps.allMatch
? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE) : Tile.STATE_UNAVAILABLE);
getQsTile().updateTile();
}
@Override
public void onClick() {
if (getQsTile().getState() == Tile.STATE_UNAVAILABLE) {
startActivityAndCollapse(new Intent(this, DevelopmentTileConfigActivity.class));
return;
}
boolean active = getQsTile().getState() == Tile.STATE_INACTIVE;
Map<String, ?> values =
getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE).getAll();
ContentResolver cr = getContentResolver();
for (Property prop : mProps.mSysProps) {
Object expected = values.get(prop.prefKey);
String value = active && !prop.isDefault(expected) ? expected.toString() : "false";
SystemProperties.set(prop.key, value);
}
for (Property prop : mProps.mSysSettings) {
boolean expectedTrue = active && !prop.isDefault(values.get(prop.prefKey));
Settings.System.putInt(cr, prop.key, expectedTrue ? 1 : 0);
}
boolean expectedGlobPropTrue = active &&
!mProps.mGlobProp.isDefault(values.get(mProps.mGlobProp.prefKey));
Settings.Global.putInt(cr, mProps.mGlobProp.key, expectedGlobPropTrue ? 1 : 0);
SystemProperties.set(mProps.mGlobProp.key, expectedGlobPropTrue ? "1" : "0");
LocalePicker.updateLocales(getResources().getConfiguration().getLocales());
IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
// Update the various animation scale values to expected values or 1. mProps.mAnimScales
// is an ordered array, where the index corresponds to the individual property.
for (int i = 0; i < mProps.mAnimScales.length; i++) {
Object expected = values.get(mProps.mAnimScales[i]);
float expectedFloat = active && expected != null ?
Float.parseFloat(expected.toString()) : 1;
wm.setAnimationScale(i, expectedFloat);
}
} catch (RemoteException e) { }
new DevelopmentSettings.SystemPropPoker().execute(); // Settings app magic
refresh();
}
static class DevModeProperties {
private final Property[] mSysProps = new Property[] {
new Property(View.DEBUG_LAYOUT_PROPERTY, DEBUG_LAYOUT_KEY),
new Property(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
SHOW_HW_SCREEN_UPDATES_KEY),
new Property(ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY,
SHOW_HW_LAYERS_UPDATES_KEY),
new Property(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY, DEBUG_HW_OVERDRAW_KEY),
new Property(ThreadedRenderer.PROFILE_PROPERTY, TRACK_FRAME_TIME_KEY),
};
private final Property[] mSysSettings = new Property[] {
new Property(Settings.System.SHOW_TOUCHES, SHOW_TOUCHES_KEY),
new Property(Settings.System.POINTER_LOCATION, POINTER_LOCATION_KEY),
};
private final Property mGlobProp =
new Property(Settings.Global.DEVELOPMENT_FORCE_RTL, FORCE_RTL_LAYOUT_KEY);
private final String[] mAnimScales = new String[] {
WINDOW_ANIMATION_SCALE_KEY,
TRANSITION_ANIMATION_SCALE_KEY,
ANIMATOR_DURATION_SCALE_KEY
};
/**
* True is the values of all the properties corresponds to the expected values. Updated when
* {@link #refreshState(Context)} is called.
*/
public boolean allMatch;
/**
* True is at least one property has a non-default expected value. Updated when
* {@link #refreshState(Context)} is called. Not that if all properties have default
* expected value, then active and non-active state will be the same.
*/
public boolean isSet;
public void refreshState(Context context) {
Map<String, ?> values =
context.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE).getAll();
allMatch = true;
// True if there is at least one non-default value.
isSet = false;
for (Property prop : mSysProps) {
Object expected = values.get(prop.prefKey);
String actual = SystemProperties.get(prop.key);
allMatch &= prop.isDefault(expected)
? prop.isDefault(actual) : expected.toString().equals(actual);
isSet |= !prop.isDefault(expected);
}
ContentResolver cr = context.getContentResolver();
for (Property prop : mSysSettings) {
boolean expectedTrue = !prop.isDefault(values.get(prop.prefKey));
isSet |= expectedTrue;
allMatch &= expectedTrue == (Settings.System.getInt(cr, prop.key, 0) != 0);
}
boolean expectedGlopPropTrue = !mGlobProp.isDefault(values.get(mGlobProp.prefKey));
isSet |= expectedGlopPropTrue;
allMatch &= expectedGlopPropTrue == (Settings.Global.getInt(cr, mGlobProp.key, 0) != 0);
IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
for (int i = 0; i < mAnimScales.length; i++) {
Object expected = values.get(mAnimScales[i]);
float expectedFloat = expected == null
? 1 : Float.parseFloat(expected.toString());
isSet |= expectedFloat != 1;
allMatch &= expectedFloat == wm.getAnimationScale(i);
}
} catch (RemoteException e) { }
}
}
private static class Property {
final String key;
final String prefKey;
Property(String key, String prefKey) {
this.key = key;
this.prefKey = prefKey;
}
boolean isDefault(Object value) {
if (value == null) {
return true;
}
String str = value.toString();
return str.equals("") || str.equals("false");
}
}
}

View File

@@ -16,16 +16,20 @@
package com.android.settings.qstile;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.view.View;
import android.service.quicksettings.TileService;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.core.instrumentation.Instrumentable;
import com.android.settings.widget.SwitchBar;
public class DevelopmentTileConfigActivity extends SettingsActivity {
@@ -42,35 +46,38 @@ public class DevelopmentTileConfigActivity extends SettingsActivity {
return (DevelopmentTileConfigFragment.class.getName().equals(fragmentName));
}
public static class DevelopmentTileConfigFragment extends SettingsPreferenceFragment implements
SharedPreferences.OnSharedPreferenceChangeListener {
private DevelopmentModeTile.DevModeProperties mProps =
new DevelopmentModeTile.DevModeProperties();
private SwitchBar mSwitchBar;
private View mDisabledMessage;
public static class DevelopmentTileConfigFragment extends SettingsPreferenceFragment
implements Preference.OnPreferenceChangeListener {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getPreferenceManager()
.setSharedPreferencesName(DevelopmentModeTile.SHARED_PREFERENCES_NAME);
addPreferencesFromResource(R.xml.development_tile_prefs);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mDisabledMessage = setPinnedHeaderView(R.layout.development_tile_config_header);
refreshHeader();
}
Context context = getPrefContext();
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(context));
getPreferenceScreen().removeAll();
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar();
mSwitchBar.setEnabled(false);
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
@@ -79,37 +86,14 @@ public class DevelopmentTileConfigActivity extends SettingsActivity {
}
@Override
public void onResume() {
super.onResume();
refreshHeader();
getPreferenceManager().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
super.onPause();
getPreferenceManager().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
refreshHeader();
}
private void refreshHeader() {
if (mSwitchBar != null && mDisabledMessage != null) {
mProps.refreshState(getActivity());
if (mProps.isSet) {
mSwitchBar.show();
mDisabledMessage.setVisibility(View.GONE);
} else {
mSwitchBar.hide();
mDisabledMessage.setVisibility(View.VISIBLE);
}
mSwitchBar.setChecked(mProps.allMatch);
}
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;
}
}
}
}

View File

@@ -0,0 +1,134 @@
/*
* 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.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.view.IWindowManager;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.WindowManagerGlobal;
import com.android.internal.app.LocalePicker;
import com.android.settings.DevelopmentSettings;
public abstract class DevelopmentTiles extends TileService {
protected abstract boolean isEnabled();
protected abstract void setIsEnabled(boolean isEnabled);
@Override
public void onStartListening() {
super.onStartListening();
refresh();
}
public void refresh() {
getQsTile().setState(isEnabled() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
getQsTile().updateTile();
}
@Override
public void onClick() {
setIsEnabled(getQsTile().getState() == Tile.STATE_INACTIVE);
new DevelopmentSettings.SystemPropPoker().execute(); // Settings app magic
refresh();
}
/**
* Tile to control the "Show layout bounds" developer setting
*/
public static class ShowLayout extends DevelopmentTiles {
@Override
protected boolean isEnabled() {
return SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false);
}
@Override
protected void setIsEnabled(boolean isEnabled) {
SystemProperties.set(View.DEBUG_LAYOUT_PROPERTY, isEnabled ? "true" : "false");
}
}
/**
* Tile to control the "GPU profiling" developer setting
*/
public static class GPUProfiling extends DevelopmentTiles {
@Override
protected boolean isEnabled() {
final String value = SystemProperties.get(ThreadedRenderer.PROFILE_PROPERTY);
return value.equals("visual_bars");
}
@Override
protected void setIsEnabled(boolean isEnabled) {
SystemProperties.set(ThreadedRenderer.PROFILE_PROPERTY, isEnabled ? "visual_bars" : "");
}
}
/**
* Tile to control the "Force RTL" developer setting
*/
public static class ForceRTL extends DevelopmentTiles {
@Override
protected boolean isEnabled() {
return Settings.Global.getInt(
getContentResolver(), Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0;
}
@Override
protected void setIsEnabled(boolean isEnabled) {
Settings.Global.putInt(
getContentResolver(), Settings.Global.DEVELOPMENT_FORCE_RTL, isEnabled ? 1 : 0);
SystemProperties.set(Settings.Global.DEVELOPMENT_FORCE_RTL, isEnabled ? "1" : "0");
LocalePicker.updateLocales(getResources().getConfiguration().getLocales());
}
}
/**
* Tile to control the "Animation speed" developer setting
*/
public static class AnimationSpeed extends DevelopmentTiles {
@Override
protected boolean isEnabled() {
IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
return wm.getAnimationScale(0) != 1;
} catch (RemoteException e) { }
return false;
}
@Override
protected void setIsEnabled(boolean isEnabled) {
IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
float scale = isEnabled ? 10 : 1;
try {
wm.setAnimationScale(0, scale);
wm.setAnimationScale(1, scale);
wm.setAnimationScale(2, scale);
} catch (RemoteException e) { }
}
}
}