diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 11e2a71a0df02..865352320800f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -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.
diff --git a/packages/SystemUI/res/drawable/ic_remove_circle.xml b/packages/SystemUI/res/drawable/ic_remove_circle.xml
new file mode 100644
index 0000000000000..439cc7896cc8b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_remove_circle.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/packages/SystemUI/res/layout/preference_widget_radiobutton.xml b/packages/SystemUI/res/layout/preference_widget_radiobutton.xml
new file mode 100644
index 0000000000000..b3ec43da3edaf
--- /dev/null
+++ b/packages/SystemUI/res/layout/preference_widget_radiobutton.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 67def4fa8ee0a..77de9a2c995cb 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1527,14 +1527,12 @@
Layout
-
- Left
-
-
- Right
+
+ Extra left button type
- Button type
+ Extra right button type
+
(default)
@@ -1543,7 +1541,7 @@
- Clipboard
- Keycode
- - Menu / Keyboard Switcher
+ - Keyboard switcher
- None
@@ -1555,10 +1553,10 @@
- - Divided (default)
- - Centered
- - Left-aligned
- - Right-aligned
+ - Normal
+ - Compact
+ - Left-leaning
+ - Right-leaning
@@ -1569,7 +1567,7 @@
- Menu / Keyboard Switcher
+ Keyboard switcher
Save
@@ -1585,10 +1583,16 @@
Custom navigation button
- Keycode
+ Left keycode
+
+
+ Right keycode
- Icon
+ Left icon
+
+
+ Right icon
Drag to add tiles
@@ -1725,6 +1729,9 @@
not appear on production builds ever. -->
Always on
+
+ Lock screen
+
Expand
@@ -1760,20 +1767,47 @@
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.
-
- Left
-
-
- Right
-
-
- Customize shortcut
+
+ Left shortcut
- Shortcut
+ Right shortcut
-
- Prompt for password
+
+ Left shortcut also unlocks
+
+
+ Right shortcut also unlocks
+
+
+ None
+
+
+ Launch %1$s
+
+
+ Other apps
+
+
+ Circle
+
+
+ Plus
+
+
+ Minus
+
+
+ Left
+
+
+ Right
+
+
+ Menu
+
+
+ %1$s app
Alerts
diff --git a/packages/SystemUI/res/xml/lockscreen_settings.xml b/packages/SystemUI/res/xml/lockscreen_settings.xml
index 73e29af428210..1e7d266cc5cc0 100644
--- a/packages/SystemUI/res/xml/lockscreen_settings.xml
+++ b/packages/SystemUI/res/xml/lockscreen_settings.xml
@@ -18,42 +18,25 @@
xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:title="@string/other">
-
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/packages/SystemUI/res/xml/nav_bar_tuner.xml b/packages/SystemUI/res/xml/nav_bar_tuner.xml
index 6fa8bec3a9376..68e8fad1e24a8 100644
--- a/packages/SystemUI/res/xml/nav_bar_tuner.xml
+++ b/packages/SystemUI/res/xml/nav_bar_tuner.xml
@@ -18,7 +18,7 @@
xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:title="@string/nav_bar">
-
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 6198ab7a3b735..c354811800756 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -121,6 +121,7 @@
+
-
-
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 void destroyDependency(Class cls, Consumer 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 void destroy(Class cls, Consumer destroy) {
+ sDependency.destroyDependency(cls, destroy);
+ }
+
public static T get(Class cls) {
return sDependency.getDependency(cls);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 187b5573b97c6..6caee5f2220e4 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -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,
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 0c6bf52e84ba3..57c75bf6f54ce 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -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;
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index 85cde10b5a530..9a8512daf58c5 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -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 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);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index f2c3e61cfe02f..4e307973d003e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -301,6 +301,7 @@ public class TileAdapter extends RecyclerView.Adapter implements TileSta
if (position == mEditIndex) position--;
move(mAccessibilityFromIndex, position, v);
+
notifyDataSetChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
new file mode 100644
index 0000000000000..e50fd5e2c5c57
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
@@ -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);
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
index 6f4a3a4969fa9..410d3d2e1b531 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -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 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);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
index 28a00570a019b..45abd456ea167 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -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 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);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
new file mode 100644
index 0000000000000..dc0d8bf6e668a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
@@ -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();
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
new file mode 100644
index 0000000000000..1d1570846a4f5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
@@ -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 "";
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
new file mode 100644
index 0000000000000..533388a1a5d8f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
@@ -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 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 activities = apps.getActivityList(null,
+ Process.myUserHandle());
+
+ screen.addPreference(otherApps);
+ activities.forEach(info -> {
+ try {
+ List 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();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 74280a315e675..4eb1db6ca670e 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -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);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
new file mode 100644
index 0000000000000..06d40da4557e1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
@@ -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");
+ }
+}