Merge "Tuner updates"

This commit is contained in:
Jason Monk
2017-02-15 20:24:41 +00:00
committed by Android (Google) Code Review
20 changed files with 881 additions and 177 deletions

View File

@@ -215,6 +215,13 @@ public class Utils {
return colorAccent;
}
public static Drawable getDrawable(Context context, int attr) {
TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
Drawable drawable = ta.getDrawable(0);
ta.recycle();
return drawable;
}
/**
* Determine whether a package is a "system package", in which case certain things (like
* disabling notifications or disabling the package altogether) should be disallowed.

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2015 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="48dp"
android:width="48dp"
android:tint="#db4437"
android:viewportHeight="48"
android:viewportWidth="48" >
<path android:fillColor="@android:color/white"
android:pathData="M24,4C12.95,4,4,12.95,4,24
s8.95,20,20,20,20-8.95,20-20
S35.05,4,24,4zm10,22H14v-4h20v4z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2006 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.
-->
<!-- Layout used by CheckBoxPreference for the checkbox style. This is inflated
inside android.R.layout.preference. -->
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:focusable="false"
android:clickable="false" />

View File

@@ -1527,14 +1527,12 @@
<!-- SysUI Tuner: Button that controls layout of navigation bar [CHAR LIMIT=60] -->
<string name="nav_bar_layout">Layout</string>
<!-- SysUI Tuner: Label for section of settings about the left nav button [CHAR LIMIT=60] -->
<string name="nav_bar_left">Left</string>
<!-- SysUI Tuner: Label for section of settings about the right nav button [CHAR LIMIT=60] -->
<string name="nav_bar_right">Right</string>
<!-- SysUI Tuner: Setting for button type in nav bar [CHAR LIMIT=60] -->
<string name="left_nav_bar_button_type">Extra left button type</string>
<!-- SysUI Tuner: Setting for button type in nav bar [CHAR LIMIT=60] -->
<string name="nav_bar_button_type">Button type</string>
<string name="right_nav_bar_button_type">Extra right button type</string>
<!-- SysUI Tuner: Added to nav bar option to indicate it is the default [CHAR LIMIT=60] -->
<string name="nav_bar_default"> (default)</string>
@@ -1543,7 +1541,7 @@
<string-array name="nav_bar_buttons">
<item>Clipboard</item>
<item>Keycode</item>
<item>Menu / Keyboard Switcher</item>
<item>Keyboard switcher</item>
<item>None</item>
</string-array>
<string-array name="nav_bar_button_values" translatable="false">
@@ -1555,10 +1553,10 @@
<!-- SysUI Tuner: Labels for different types of navigation bar layouts [CHAR LIMIT=60] -->
<string-array name="nav_bar_layouts">
<item>Divided (default)</item>
<item>Centered</item>
<item>Left-aligned</item>
<item>Right-aligned</item>
<item>Normal</item>
<item>Compact</item>
<item>Left-leaning</item>
<item>Right-leaning</item>
</string-array>
<string-array name="nav_bar_layouts_values" translatable="false">
@@ -1569,7 +1567,7 @@
</string-array>
<!-- SysUI Tuner: Name of Combination Menu / Keyboard Switcher button [CHAR LIMIT=30] -->
<string name="menu_ime">Menu / Keyboard Switcher</string>
<string name="menu_ime">Keyboard switcher</string>
<!-- SysUI Tuner: Save the current settings [CHAR LIMIT=30] -->
<string name="save">Save</string>
<!-- SysUI Tuner: Reset to default settings [CHAR LIMIT=30] -->
@@ -1585,10 +1583,16 @@
<string name="accessibility_key">Custom navigation button</string>
<!-- SysUI Tuner: Nav bar button that emulates a keycode [CHAR LIMIT=30] -->
<string name="keycode">Keycode</string>
<string name="left_keycode">Left keycode</string>
<!-- SysUI Tuner: Nav bar button that emulates a keycode [CHAR LIMIT=30] -->
<string name="right_keycode">Right keycode</string>
<!-- SysUI Tuner: Settings to change nav bar icon [CHAR LIMIT=30] -->
<string name="icon">Icon</string>
<string name="left_icon">Left icon</string>
<!-- SysUI Tuner: Settings to change nav bar icon [CHAR LIMIT=30] -->
<string name="right_icon">Right icon</string>
<!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
<string name="drag_to_add_tiles">Drag to add tiles</string>
@@ -1725,6 +1729,9 @@
not appear on production builds ever. -->
<string name="tuner_doze_always_on" translatable="false">Always on</string>
<!-- SysUI Tuner: Section to customize lockscreen shortcuts [CHAR LIMIT=60] -->
<string name="tuner_lock_screen">Lock screen</string>
<!-- Making the PIP fullscreen [CHAR LIMIT=25] -->
<string name="pip_phone_expand">Expand</string>
@@ -1760,20 +1767,47 @@
<!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=300] -->
<string name="high_temp_dialog_message">Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally.</string>
<!-- SysUI Tuner: Group of settings for left lock screen affordance [CHAR LIMIT=60] -->
<string name="lockscreen_left">Left</string>
<!-- SysUI Tuner: Group of settings for right lock screen affordance [CHAR LIMIT=60] -->
<string name="lockscreen_right">Right</string>
<!-- SysUI Tuner: Switch controlling whether to customize lock screen button [CHAR LIMIT=60] -->
<string name="lockscreen_customize">Customize shortcut</string>
<!-- SysUI Tuner: Button to select lock screen shortcut [CHAR LIMIT=60] -->
<string name="lockscreen_shortcut_left">Left shortcut</string>
<!-- SysUI Tuner: Button to select lock screen shortcut [CHAR LIMIT=60] -->
<string name="lockscreen_shortcut">Shortcut</string>
<string name="lockscreen_shortcut_right">Right shortcut</string>
<!-- SysUI Tuner: Switch to control if device gets unlocked [CHAR LIMIT=60] -->
<string name="lockscreen_unlock">Prompt for password</string>
<!-- SysUI Tuner: Switch to control if device gets unlocked by left shortcut [CHAR LIMIT=60] -->
<string name="lockscreen_unlock_left">Left shortcut also unlocks</string>
<!-- SysUI Tuner: Switch to control if device gets unlocked by right shortcut [CHAR LIMIT=60] -->
<string name="lockscreen_unlock_right">Right shortcut also unlocks</string>
<!-- SysUI Tuner: Summary of no shortcut being selected [CHAR LIMIT=60] -->
<string name="lockscreen_none">None</string>
<!-- SysUI Tuner: Format string for describing launching an app [CHAR LIMIT=60] -->
<string name="tuner_launch_app">Launch <xliff:g id="app" example="Settings">%1$s</xliff:g></string>
<!-- SysUI Tuner: Label for section of other apps that can be launched [CHAR LIMIT=60] -->
<string name="tuner_other_apps">Other apps</string>
<!-- SysUI Tuner: Label for icon shaped like a circle [CHAR LIMIT=60] -->
<string name="tuner_circle">Circle</string>
<!-- SysUI Tuner: Label for icon shaped like a plus [CHAR LIMIT=60] -->
<string name="tuner_plus">Plus</string>
<!-- SysUI Tuner: Label for icon shaped like a minus [CHAR LIMIT=60] -->
<string name="tuner_minus">Minus</string>
<!-- SysUI Tuner: Label for icon shaped like a left [CHAR LIMIT=60] -->
<string name="tuner_left">Left</string>
<!-- SysUI Tuner: Label for icon shaped like a right [CHAR LIMIT=60] -->
<string name="tuner_right">Right</string>
<!-- SysUI Tuner: Label for icon shaped like a menu [CHAR LIMIT=60] -->
<string name="tuner_menu">Menu</string>
<!-- SysUI Tuner: App subheading for shortcut selection [CHAR LIMIT=60] -->
<string name="tuner_app"><xliff:g id="app">%1$s</xliff:g> app</string>
<!-- Title for the notification channel containing important alerts like low battery. [CHAR LIMIT=NONE] -->
<string name="notification_channel_alerts">Alerts</string>

View File

@@ -18,42 +18,25 @@
xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:title="@string/other">
<PreferenceCategory
android:key="left"
android:title="@string/lockscreen_left">
<SwitchPreference
android:key="customize"
android:title="@string/lockscreen_customize" />
<Preference
android:key="sysui_keyguard_left"
android:title="@string/lockscreen_shortcut_left"
android:fragment="com.android.systemui.tuner.ShortcutPicker" />
<Preference
android:key="shortcut"
android:title="@string/lockscreen_shortcut" />
<com.android.systemui.tuner.TunerSwitch
android:key="sysui_keyguard_left_unlock"
android:title="@string/lockscreen_unlock_left"
sysui:defValue="true" />
<com.android.systemui.tuner.TunerSwitch
android:key="sysui_keyguard_left_unlock"
android:title="@string/lockscreen_unlock"
sysui:defValue="true" />
<Preference
android:key="sysui_keyguard_right"
android:title="@string/lockscreen_shortcut_right"
android:fragment="com.android.systemui.tuner.ShortcutPicker" />
</PreferenceCategory>
<PreferenceCategory
android:key="right"
android:title="@string/lockscreen_right">
<SwitchPreference
android:key="customize"
android:title="@string/lockscreen_customize" />
<Preference
android:key="shortcut"
android:title="@string/lockscreen_shortcut" />
<com.android.systemui.tuner.TunerSwitch
android:key="sysui_keyguard_right_unlock"
android:title="@string/lockscreen_unlock"
sysui:defValue="true" />
</PreferenceCategory>
<com.android.systemui.tuner.TunerSwitch
android:key="sysui_keyguard_right_unlock"
android:title="@string/lockscreen_unlock_right"
sysui:defValue="true" />
</PreferenceScreen>

View File

@@ -18,7 +18,7 @@
xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:title="@string/nav_bar">
<ListPreference
<com.android.systemui.tuner.RadioListPreference
android:key="layout"
android:title="@string/nav_bar_layout"
android:summary="%s"
@@ -26,54 +26,42 @@
android:entries="@array/nav_bar_layouts"
android:entryValues="@array/nav_bar_layouts_values" />
<PreferenceCategory
android:key="left"
android:title="@string/nav_bar_left">
<com.android.systemui.tuner.RadioListPreference
android:key="type_left"
android:title="@string/left_nav_bar_button_type"
android:persistent="false"
android:summary="%s"
android:entries="@array/nav_bar_buttons"
android:entryValues="@array/nav_bar_button_values" />
<DropDownPreference
android:key="type_left"
android:title="@string/nav_bar_button_type"
android:persistent="false"
android:summary="%s"
android:entries="@array/nav_bar_buttons"
android:entryValues="@array/nav_bar_button_values" />
<Preference
android:key="keycode_left"
android:persistent="false"
android:title="@string/left_keycode" />
<Preference
android:key="keycode_left"
android:persistent="false"
android:title="@string/keycode" />
<com.android.systemui.tuner.RadioListPreference
android:key="icon_left"
android:persistent="false"
android:summary="%s"
android:title="@string/left_icon" />
<com.android.systemui.tuner.BetterListPreference
android:key="icon_left"
android:persistent="false"
android:summary="%s"
android:title="@string/icon" />
<com.android.systemui.tuner.RadioListPreference
android:key="type_right"
android:title="@string/right_nav_bar_button_type"
android:summary="%s"
android:persistent="false"
android:entries="@array/nav_bar_buttons"
android:entryValues="@array/nav_bar_button_values" />
</PreferenceCategory>
<Preference
android:key="keycode_right"
android:persistent="false"
android:title="@string/right_keycode" />
<PreferenceCategory
android:key="right"
android:title="@string/nav_bar_right">
<DropDownPreference
android:key="type_right"
android:title="@string/nav_bar_button_type"
android:summary="%s"
android:persistent="false"
android:entries="@array/nav_bar_buttons"
android:entryValues="@array/nav_bar_button_values" />
<Preference
android:key="keycode_right"
android:persistent="false"
android:title="@string/keycode" />
<com.android.systemui.tuner.BetterListPreference
android:key="icon_right"
android:persistent="false"
android:summary="%s"
android:title="@string/icon" />
</PreferenceCategory>
<com.android.systemui.tuner.RadioListPreference
android:key="icon_right"
android:persistent="false"
android:summary="%s"
android:title="@string/right_icon" />
</PreferenceScreen>

View File

@@ -121,6 +121,7 @@
</PreferenceScreen>
<!--
<PreferenceScreen
android:key="picture_in_picture"
android:title="@string/picture_in_picture">
@@ -143,6 +144,7 @@
sysui:defValue="false" />
</PreferenceScreen>
-->
<Preference
android:key="nav_bar"
@@ -151,14 +153,9 @@
<Preference
android:key="lockscreen"
android:title="@string/accessibility_desc_lock_screen"
android:title="@string/tuner_lock_screen"
android:fragment="com.android.systemui.tuner.LockscreenFragment" />
<Preference
android:key="other"
android:title="@string/other"
android:fragment="com.android.systemui.tuner.OtherPrefs" />
<Preference
android:key="plugins"
android:title="@string/plugins"

View File

@@ -25,6 +25,8 @@ import android.util.ArrayMap;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
@@ -74,6 +76,7 @@ import com.android.systemui.util.leak.LeakReporter;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.function.Consumer;
/**
* Class to handle ugly dependencies throughout sysui until we determine the
@@ -227,6 +230,9 @@ public class Dependency extends SystemUI {
mProviders.put(StatusBarIconController.class, () ->
new StatusBarIconControllerImpl(mContext));
mProviders.put(FragmentService.class, () ->
new FragmentService(mContext));
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
@@ -282,17 +288,42 @@ public class Dependency extends SystemUI {
T createDependency();
}
private <T> void destroyDependency(Class<T> cls, Consumer<T> destroy) {
T dep = (T) mDependencies.remove(cls);
if (dep != null && destroy != null) {
destroy.accept(dep);
}
}
/**
* Used in separate processes (like tuner settings) to init the dependencies.
*/
public static void initDependencies(Context context) {
if (sDependency != null) return;
Dependency d = new Dependency();
d.mContext = context.getApplicationContext();
d.mContext = context;
d.mComponents = new HashMap<>();
d.start();
}
/**
* Used in separate process teardown to ensure the context isn't leaked.
*
* TODO: Remove once PreferenceFragment doesn't reference getActivity()
* anymore and these context hacks are no longer needed.
*/
public static void clearDependencies() {
sDependency = null;
}
/**
* Checks to see if a dependency is instantiated, if it is it removes it from
* the cache and calls the destroy callback.
*/
public static <T> void destroy(Class<T> cls, Consumer<T> destroy) {
sDependency.destroyDependency(cls, destroy);
}
public static <T> T get(Class<T> cls) {
return sDependency.getDependency(cls);
}

View File

@@ -67,7 +67,6 @@ public class SystemUIApplication extends Application implements SysUiServiceProv
*/
private final Class<?>[] SERVICES = new Class[] {
Dependency.class,
FragmentService.class,
NotificationChannels.class,
CommandQueue.CommandQueueStart.class,
KeyguardViewMediator.class,

View File

@@ -32,6 +32,7 @@ import android.view.LayoutInflater;
import android.view.View;
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.Dependency;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginManager;
@@ -171,6 +172,10 @@ public class FragmentHostManager {
return mPlugins;
}
void destroy() {
mFragments.dispatchDestroy();
}
public interface FragmentListener {
void onFragmentViewCreated(String tag, Fragment fragment);
@@ -182,8 +187,7 @@ public class FragmentHostManager {
public static FragmentHostManager get(View view) {
try {
return ((SystemUIApplication) view.getContext().getApplicationContext())
.getComponent(FragmentService.class).getFragmentHostManager(view);
return Dependency.get(FragmentService.class).getFragmentHostManager(view);
} catch (ClassCastException e) {
// TODO: Some auto handling here?
throw e;

View File

@@ -14,6 +14,7 @@
package com.android.systemui.fragments;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
@@ -21,6 +22,7 @@ import android.util.ArrayMap;
import android.util.Log;
import android.view.View;
import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;
@@ -28,16 +30,16 @@ import com.android.systemui.SystemUIApplication;
* Holds a map of root views to FragmentHostStates and generates them as needed.
* Also dispatches the configuration changes to all current FragmentHostStates.
*/
public class FragmentService extends SystemUI {
public class FragmentService implements ConfigurationChangedReceiver {
private static final String TAG = "FragmentService";
private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>();
private final Handler mHandler = new Handler();
private final Context mContext;
@Override
public void start() {
putComponent(FragmentService.class, this);
public FragmentService(Context context) {
mContext = context;
}
public FragmentHostManager getFragmentHostManager(View view) {
@@ -50,8 +52,14 @@ public class FragmentService extends SystemUI {
return state.getFragmentHostManager();
}
public void destroyAll() {
for (FragmentHostState state : mHosts.values()) {
state.mFragmentHostManager.destroy();
}
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
public void onConfigurationChanged(Configuration newConfig) {
for (FragmentHostState state : mHosts.values()) {
state.sendConfigurationChange(newConfig);
}

View File

@@ -301,6 +301,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
if (position == mEditIndex) position--;
move(mAccessibilityFromIndex, position, v);
notifyDataSetChanged();
}

View File

@@ -0,0 +1,173 @@
/*
* 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.systemui.tuner;
import android.annotation.Nullable;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.support.v14.preference.ListPreferenceDialogFragment;
import android.support.v7.preference.ListPreference;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class CustomListPreference extends ListPreference {
public CustomListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomListPreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
OnClickListener listener) {
}
protected void onDialogClosed(boolean positiveResult) {
}
protected Dialog onDialogCreated(DialogFragment fragment, Dialog dialog) {
return dialog;
}
protected boolean isAutoClosePreference() {
return true;
}
/**
* Called when a user is about to choose the given value, to determine if we
* should show a confirmation dialog.
*
* @param value the value the user is about to choose
* @return the message to show in a confirmation dialog, or {@code null} to
* not request confirmation
*/
protected CharSequence getConfirmationMessage(String value) {
return null;
}
protected void onDialogStateRestored(DialogFragment fragment, Dialog dialog,
Bundle savedInstanceState) {
}
public static class CustomListPreferenceDialogFragment extends ListPreferenceDialogFragment {
private static final String KEY_CLICKED_ENTRY_INDEX
= "settings.CustomListPrefDialog.KEY_CLICKED_ENTRY_INDEX";
private int mClickedDialogEntryIndex;
public static ListPreferenceDialogFragment newInstance(String key) {
final ListPreferenceDialogFragment fragment = new CustomListPreferenceDialogFragment();
final Bundle b = new Bundle(1);
b.putString(ARG_KEY, key);
fragment.setArguments(b);
return fragment;
}
public CustomListPreference getCustomizablePreference() {
return (CustomListPreference) getPreference();
}
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
mClickedDialogEntryIndex = getCustomizablePreference()
.findIndexOfValue(getCustomizablePreference().getValue());
getCustomizablePreference().onPrepareDialogBuilder(builder, getOnItemClickListener());
if (!getCustomizablePreference().isAutoClosePreference()) {
builder.setPositiveButton(com.android.internal.R.string.ok, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
onItemConfirmed();
}
});
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
if (savedInstanceState != null) {
mClickedDialogEntryIndex = savedInstanceState.getInt(KEY_CLICKED_ENTRY_INDEX,
mClickedDialogEntryIndex);
}
return getCustomizablePreference().onDialogCreated(this, dialog);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_CLICKED_ENTRY_INDEX, mClickedDialogEntryIndex);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getCustomizablePreference().onDialogStateRestored(this, getDialog(), savedInstanceState);
}
protected OnClickListener getOnItemClickListener() {
return new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setClickedDialogEntryIndex(which);
if (getCustomizablePreference().isAutoClosePreference()) {
onItemConfirmed();
}
}
};
}
protected void setClickedDialogEntryIndex(int which) {
mClickedDialogEntryIndex = which;
}
private String getValue() {
final ListPreference preference = getCustomizablePreference();
if (mClickedDialogEntryIndex >= 0 && preference.getEntryValues() != null) {
return preference.getEntryValues()[mClickedDialogEntryIndex].toString();
} else {
return null;
}
}
protected void onItemConfirmed() {
onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);
getDialog().dismiss();
}
@Override
public void onDialogClosed(boolean positiveResult) {
getCustomizablePreference().onDialogClosed(positiveResult);
final ListPreference preference = getCustomizablePreference();
final String value = getValue();
if (positiveResult && value != null) {
if (preference.callChangeListener(value)) {
preference.setValue(value);
}
}
}
}
}

View File

@@ -80,10 +80,8 @@ public class LockscreenFragment extends PreferenceFragment {
mTunerService = Dependency.get(TunerService.class);
mHandler = new Handler();
addPreferencesFromResource(R.xml.lockscreen_settings);
setupGroup((PreferenceGroup) findPreference(KEY_LEFT), LOCKSCREEN_LEFT_BUTTON,
LOCKSCREEN_LEFT_UNLOCK);
setupGroup((PreferenceGroup) findPreference(KEY_RIGHT), LOCKSCREEN_RIGHT_BUTTON,
LOCKSCREEN_RIGHT_UNLOCK);
setupGroup(LOCKSCREEN_LEFT_BUTTON, LOCKSCREEN_LEFT_UNLOCK);
setupGroup(LOCKSCREEN_RIGHT_BUTTON, LOCKSCREEN_RIGHT_UNLOCK);
}
@Override
@@ -92,30 +90,14 @@ public class LockscreenFragment extends PreferenceFragment {
mTunables.forEach(t -> mTunerService.removeTunable(t));
}
private void setupGroup(PreferenceGroup group, String buttonSetting, String unlockKey) {
SwitchPreference customize = (SwitchPreference) group.findPreference(KEY_CUSTOMIZE);
Preference shortcut = group.findPreference(KEY_SHORTCUT);
SwitchPreference unlock = (SwitchPreference) group.findPreference(unlockKey);
private void setupGroup(String buttonSetting, String unlockKey) {
Preference shortcut = findPreference(buttonSetting);
SwitchPreference unlock = (SwitchPreference) findPreference(unlockKey);
addTunable((k, v) -> {
boolean visible = v != null;
customize.setChecked(visible);
shortcut.setVisible(visible);
boolean visible = !TextUtils.isEmpty(v);
unlock.setVisible(visible);
if (visible) {
setSummary(shortcut, v);
}
setSummary(shortcut, v);
}, buttonSetting);
customize.setOnPreferenceChangeListener((preference, newValue) -> {
boolean hasSetting = mTunerService.getValue(buttonSetting) != null;
if (hasSetting != (boolean) newValue) {
mHandler.post(() -> mTunerService.setValue(buttonSetting, hasSetting ? null : ""));
}
return true;
});
shortcut.setOnPreferenceClickListener(preference -> {
showSelectDialog(buttonSetting);
return true;
});
}
private void showSelectDialog(String buttonSetting) {
@@ -129,24 +111,15 @@ public class LockscreenFragment extends PreferenceFragment {
mTunerService.setValue(buttonSetting, item.getSettingValue());
dialog.dismiss();
});
LauncherApps apps = getContext().getSystemService(LauncherApps.class);
List<LauncherActivityInfo> activities = apps.getActivityList(null,
Process.myUserHandle());
activities.forEach(info -> {
App app = new App(getContext(), info);
try {
new ShortcutParser(getContext(), info.getComponentName()).getShortcuts().forEach(
shortcut -> app.addChild(new StaticShortcut(getContext(), shortcut)));
} catch (NameNotFoundException e) {
}
adapter.addItem(app);
});
v.setAdapter(adapter);
}
private void setSummary(Preference shortcut, String value) {
if (value == null) {
shortcut.setSummary(R.string.lockscreen_none);
return;
}
if (value.contains("::")) {
Shortcut info = getShortcutInfo(getContext(), value);
shortcut.setSummary(info != null ? info.label : null);
@@ -155,7 +128,7 @@ public class LockscreenFragment extends PreferenceFragment {
shortcut.setSummary(info != null ? info.loadLabel(getContext().getPackageManager())
: null);
} else {
shortcut.setSummary(null);
shortcut.setSummary(R.string.lockscreen_none);
}
}

View File

@@ -33,6 +33,9 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
@@ -58,7 +61,7 @@ import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
public class NavBarTuner extends PreferenceFragment {
public class NavBarTuner extends TunerPreferenceFragment {
private static final String LAYOUT = "layout";
private static final String LEFT = "left";
@@ -68,13 +71,13 @@ public class NavBarTuner extends PreferenceFragment {
private static final String KEYCODE = "keycode";
private static final String ICON = "icon";
private static final int[] ICONS = new int[]{
R.drawable.ic_qs_circle,
R.drawable.ic_add,
R.drawable.ic_remove,
R.drawable.ic_left,
R.drawable.ic_right,
R.drawable.ic_menu,
private static final int[][] ICONS = new int[][]{
{R.drawable.ic_qs_circle, R.string.tuner_circle},
{R.drawable.ic_add, R.string.tuner_plus},
{R.drawable.ic_remove, R.string.tuner_minus},
{R.drawable.ic_left, R.string.tuner_left},
{R.drawable.ic_right, R.string.tuner_right},
{R.drawable.ic_menu, R.string.tuner_menu},
};
private final ArrayList<Tunable> mTunables = new ArrayList<>();
@@ -96,10 +99,8 @@ public class NavBarTuner extends PreferenceFragment {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.nav_bar_tuner);
bindLayout((ListPreference) findPreference(LAYOUT));
bindButton((PreferenceCategory) findPreference(LEFT),
NAV_BAR_LEFT, NAVSPACE);
bindButton((PreferenceCategory) findPreference(RIGHT),
NAV_BAR_RIGHT, MENU_IME);
bindButton(NAV_BAR_LEFT, NAVSPACE, LEFT);
bindButton(NAV_BAR_RIGHT, MENU_IME, RIGHT);
}
@Override
@@ -129,9 +130,8 @@ public class NavBarTuner extends PreferenceFragment {
});
}
private void bindButton(PreferenceCategory parent, String setting, String def) {
String k = parent.getKey();
DropDownPreference type = (DropDownPreference) findPreference(TYPE + "_" + k);
private void bindButton(String setting, String def, String k) {
ListPreference type = (ListPreference) findPreference(TYPE + "_" + k);
Preference keycode = findPreference(KEYCODE + "_" + k);
ListPreference icon = (ListPreference) findPreference(ICON + "_" + k);
setupIcons(icon);
@@ -195,8 +195,14 @@ public class NavBarTuner extends PreferenceFragment {
.loadDrawable(getContext());
d.setTint(Color.BLACK);
d.setBounds(0, 0, size, size);
ImageSpan span = new ImageSpan(d);
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
builder.append(" ", span, 0);
builder.append(" ");
for (int i = 0; i < ICONS.length; i++) {
if (ICONS[i][0] == id) {
builder.append(getString(ICONS[i][1]));
}
}
icon.setSummary(builder);
} catch (Exception e) {
Log.d("NavButton", "Problem with summary", e);
@@ -204,7 +210,7 @@ public class NavBarTuner extends PreferenceFragment {
}
}
private void setValue(String setting, DropDownPreference type, Preference keycode,
private void setValue(String setting, ListPreference type, Preference keycode,
ListPreference icon) {
String button = type.getValue();
if (KEY.equals(button)) {
@@ -226,14 +232,16 @@ public class NavBarTuner extends PreferenceFragment {
getContext().getResources().getDisplayMetrics());
for (int i = 0; i < ICONS.length; i++) {
SpannableStringBuilder builder = new SpannableStringBuilder();
Drawable d = Icon.createWithResource(getContext().getPackageName(), ICONS[i])
Drawable d = Icon.createWithResource(getContext().getPackageName(), ICONS[i][0])
.loadDrawable(getContext());
d.setTint(Color.BLACK);
d.setBounds(0, 0, size, size);
ImageSpan span = new ImageSpan(d);
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
builder.append(" ", span, 0);
builder.append(" ");
builder.append(getString(ICONS[i][1]));
labels[i] = builder;
values[i] = getContext().getPackageName() + "/" + ICONS[i];
values[i] = getContext().getPackageName() + "/" + ICONS[i][0];
}
icon.setEntries(labels);
icon.setEntryValues(values);

View File

@@ -0,0 +1,145 @@
/*
* 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.systemui.tuner;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.Toolbar;
import com.android.settingslib.Utils;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.R;
import libcore.util.Objects;
public class RadioListPreference extends CustomListPreference {
private OnClickListener mOnClickListener;
private CharSequence mSummary;
public RadioListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onPrepareDialogBuilder(Builder builder, OnClickListener listener) {
mOnClickListener = listener;
}
@Override
public void setSummary(CharSequence summary) {
super.setSummary(summary);
mSummary = summary;
}
@Override
public CharSequence getSummary() {
if (mSummary == null || mSummary.toString().contains("%s")) {
return super.getSummary();
}
return mSummary;
}
@Override
protected Dialog onDialogCreated(DialogFragment fragment, Dialog dialog) {
Dialog d = new Dialog(getContext(), android.R.style.Theme_DeviceDefault_Settings);
Toolbar t = (Toolbar) d.findViewById(com.android.internal.R.id.action_bar);
View v = new View(getContext());
v.setId(R.id.content);
d.setContentView(v);
t.setTitle(getTitle());
t.setNavigationIcon(Utils.getDrawable(d.getContext(), android.R.attr.homeAsUpIndicator));
t.setNavigationOnClickListener(view -> d.dismiss());
RadioFragment f = new RadioFragment();
f.setPreference(this);
FragmentHostManager.get(v).getFragmentManager()
.beginTransaction()
.add(android.R.id.content, f)
.commit();
return d;
}
@Override
protected void onDialogStateRestored(DialogFragment fragment, Dialog dialog,
Bundle savedInstanceState) {
super.onDialogStateRestored(fragment, dialog, savedInstanceState);
View view = dialog.findViewById(R.id.content);
RadioFragment radioFragment = (RadioFragment) FragmentHostManager.get(view)
.getFragmentManager().findFragmentById(R.id.content);
if (radioFragment != null) {
radioFragment.setPreference(this);
}
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
}
public static class RadioFragment extends TunerPreferenceFragment {
private RadioListPreference mListPref;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
Context context = getPreferenceManager().getContext();
PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(context);
setPreferenceScreen(screen);
if (mListPref != null) {
update();
}
}
private void update() {
Context context = getPreferenceManager().getContext();
CharSequence[] entries = mListPref.getEntries();
CharSequence[] values = mListPref.getEntryValues();
CharSequence current = mListPref.getValue();
for (int i = 0; i < entries.length; i++) {
CharSequence entry = entries[i];
SelectablePreference pref = new SelectablePreference(context);
getPreferenceScreen().addPreference(pref);
pref.setTitle(entry);
pref.setChecked(Objects.equal(current, values[i]));
pref.setKey(String.valueOf(i));
}
}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
mListPref.mOnClickListener.onClick(null, Integer.parseInt(preference.getKey()));
return true;
}
public void setPreference(RadioListPreference radioListPreference) {
mListPref = radioListPreference;
if (getPreferenceManager() != null) {
update();
}
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* 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.systemui.tuner;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v7.preference.CheckBoxPreference;
import android.util.TypedValue;
import com.android.systemui.statusbar.ScalingDrawableWrapper;
public class SelectablePreference extends CheckBoxPreference {
private final int mSize;
public SelectablePreference(Context context) {
super(context);
setWidgetLayoutResource(com.android.systemui.R.layout.preference_widget_radiobutton);
setSelectable(true);
mSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32,
context.getResources().getDisplayMetrics());
}
@Override
public void setIcon(Drawable icon) {
super.setIcon(new ScalingDrawableWrapper(icon,
mSize / (float) icon.getIntrinsicWidth()));
}
@Override
public String toString() {
return "";
}
}

View File

@@ -0,0 +1,200 @@
/*
* 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.systemui.tuner;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
import android.content.Context;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Process;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.PreferenceViewHolder;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.tuner.ShortcutParser.Shortcut;
import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
import java.util.List;
public class ShortcutPicker extends PreferenceFragment implements Tunable {
private final ArrayList<SelectablePreference> mSelectablePreferences = new ArrayList<>();
private String mKey;
private SelectablePreference mNonePreference;
private TunerService mTunerService;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
Context context = getPreferenceManager().getContext();
PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(context);
screen.setOrderingAsAdded(true);
PreferenceCategory otherApps = new PreferenceCategory(context);
otherApps.setTitle(R.string.tuner_other_apps);
mNonePreference = new SelectablePreference(context);
mSelectablePreferences.add(mNonePreference);
mNonePreference.setTitle(R.string.lockscreen_none);
mNonePreference.setIcon(R.drawable.ic_remove_circle);
screen.addPreference(mNonePreference);
LauncherApps apps = getContext().getSystemService(LauncherApps.class);
List<LauncherActivityInfo> activities = apps.getActivityList(null,
Process.myUserHandle());
screen.addPreference(otherApps);
activities.forEach(info -> {
try {
List<Shortcut> shortcuts = new ShortcutParser(getContext(),
info.getComponentName()).getShortcuts();
AppPreference appPreference = new AppPreference(context, info);
mSelectablePreferences.add(appPreference);
if (shortcuts.size() != 0) {
//PreferenceCategory category = new PreferenceCategory(context);
//screen.addPreference(category);
//category.setTitle(info.getLabel());
screen.addPreference(appPreference);
shortcuts.forEach(shortcut -> {
ShortcutPreference shortcutPref = new ShortcutPreference(context, shortcut,
info.getLabel());
mSelectablePreferences.add(shortcutPref);
screen.addPreference(shortcutPref);
});
return;
}
otherApps.addPreference(appPreference);
} catch (NameNotFoundException e) {
}
});
// Move other apps to the bottom.
screen.removePreference(otherApps);
for (int i = 0; i < otherApps.getPreferenceCount(); i++) {
Preference p = otherApps.getPreference(0);
otherApps.removePreference(p);
p.setOrder(Preference.DEFAULT_ORDER);
screen.addPreference(p);
}
//screen.addPreference(otherApps);
setPreferenceScreen(screen);
mKey = getArguments().getString(ARG_PREFERENCE_ROOT);
mTunerService = Dependency.get(TunerService.class);
mTunerService.addTunable(this, mKey);
}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
mTunerService.setValue(mKey, preference.toString());
getActivity().onBackPressed();
return true;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (LOCKSCREEN_LEFT_BUTTON.equals(mKey)) {
getActivity().setTitle(R.string.lockscreen_shortcut_left);
} else {
getActivity().setTitle(R.string.lockscreen_shortcut_right);
}
}
@Override
public void onDestroy() {
super.onDestroy();
mTunerService.removeTunable(this);
}
@Override
public void onTuningChanged(String key, String newValue) {
String v = newValue != null ? newValue : "";
mSelectablePreferences.forEach(p -> p.setChecked(v.equals(p.toString())));
}
private static class AppPreference extends SelectablePreference {
private final LauncherActivityInfo mInfo;
private boolean mBinding;
public AppPreference(Context context, LauncherActivityInfo info) {
super(context);
mInfo = info;
setTitle(context.getString(R.string.tuner_launch_app, info.getLabel()));
setSummary(context.getString(R.string.tuner_app, info.getLabel()));
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
mBinding = true;
if (getIcon() == null) {
setIcon(mInfo.getBadgedIcon(
getContext().getResources().getConfiguration().densityDpi));
}
mBinding = false;
super.onBindViewHolder(holder);
}
@Override
protected void notifyChanged() {
if (mBinding) return;
super.notifyChanged();
}
@Override
public String toString() {
return mInfo.getComponentName().flattenToString();
}
}
private static class ShortcutPreference extends SelectablePreference {
private final Shortcut mShortcut;
private boolean mBinding;
public ShortcutPreference(Context context, Shortcut shortcut, CharSequence appLabel) {
super(context);
mShortcut = shortcut;
setTitle(shortcut.label);
setSummary(context.getString(R.string.tuner_app, appLabel));
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
mBinding = true;
if (getIcon() == null) {
setIcon(mShortcut.icon.loadDrawable(getContext()));
}
mBinding = false;
super.onBindViewHolder(holder);
}
@Override
protected void notifyChanged() {
if (mBinding) return;
super.notifyChanged();
}
@Override
public String toString() {
return mShortcut.toString();
}
}
}

View File

@@ -22,10 +22,12 @@ import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import android.view.MenuItem;
import com.android.settingslib.drawer.SettingsDrawerActivity;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.fragments.FragmentService;
public class TunerActivity extends SettingsDrawerActivity implements
PreferenceFragment.OnPreferenceStartFragmentCallback,
@@ -50,6 +52,22 @@ public class TunerActivity extends SettingsDrawerActivity implements
}
}
@Override
protected void onDestroy() {
super.onDestroy();
Dependency.destroy(FragmentService.class, s -> s.destroyAll());
Dependency.clearDependencies();
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onMenuItemSelected(featureId, item);
}
@Override
public void onBackPressed() {
if (!getFragmentManager().popBackStackImmediate()) {
@@ -62,6 +80,9 @@ public class TunerActivity extends SettingsDrawerActivity implements
try {
Class<?> cls = Class.forName(pref.getFragment());
Fragment fragment = (Fragment) cls.newInstance();
final Bundle b = new Bundle(1);
b.putString(PreferenceFragment.ARG_PREFERENCE_ROOT, pref.getKey());
fragment.setArguments(b);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
setTitle(pref.getTitle());
transaction.replace(R.id.content_frame, fragment);

View File

@@ -0,0 +1,36 @@
/*
* 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.systemui.tuner;
import android.app.DialogFragment;
import android.os.Bundle;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.Preference;
public abstract class TunerPreferenceFragment extends PreferenceFragment {
@Override
public void onDisplayPreferenceDialog(Preference preference) {
DialogFragment f = null;
if (preference instanceof CustomListPreference) {
f = CustomListPreference.CustomListPreferenceDialogFragment
.newInstance(preference.getKey());
} else {
super.onDisplayPreferenceDialog(preference);
}
f.setTargetFragment(this, 0);
f.show(getFragmentManager(), "dialog_preference");
}
}