public static final String NOTIFICATION_BADGING = "notification_badging";
/**
+ * Comma separated list of QS tiles that have been auto-added already.
+ * @hide
+ */
+ public static final String QS_AUTO_ADDED_TILES = "qs_auto_tiles";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
ASSIST_GESTURE_WAKE_ENABLED,
VR_DISPLAY_MODE,
- NOTIFICATION_BADGING
+ NOTIFICATION_BADGING,
+ QS_AUTO_ADDED_TILES,
};
/**
String DND_FAVORITE_BUCKET_INDEX = "DndCountdownMinuteIndex";
String DND_NONE_SELECTED = "DndNoneSelected";
String DND_FAVORITE_ZEN = "DndFavoriteZen";
+ String QS_DATA_SAVER_DIALOG_SHOWN = "QsDataSaverDialogShown";
+ @Deprecated
String QS_HOTSPOT_ADDED = "QsHotspotAdded";
+ @Deprecated
String QS_DATA_SAVER_ADDED = "QsDataSaverAdded";
- String QS_DATA_SAVER_DIALOG_SHOWN = "QsDataSaverDialogShown";
+ @Deprecated
String QS_INVERT_COLORS_ADDED = "QsInvertColorsAdded";
+ @Deprecated
String QS_WORK_ADDED = "QsWorkAdded";
+ @Deprecated
String QS_NIGHTDISPLAY_ADDED = "QsNightDisplayAdded";
}
--- /dev/null
+/*
+ * 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.qs;
+
+import static com.android.systemui.statusbar.phone.AutoTileManager.HOTSPOT;
+import static com.android.systemui.statusbar.phone.AutoTileManager.INVERSION;
+import static com.android.systemui.statusbar.phone.AutoTileManager.NIGHT;
+import static com.android.systemui.statusbar.phone.AutoTileManager.SAVER;
+import static com.android.systemui.statusbar.phone.AutoTileManager.WORK;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.provider.Settings.Secure;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public class AutoAddTracker {
+
+ private static final String[][] CONVERT_PREFS = {
+ {Key.QS_HOTSPOT_ADDED, HOTSPOT},
+ {Key.QS_DATA_SAVER_ADDED, SAVER},
+ {Key.QS_INVERT_COLORS_ADDED, INVERSION},
+ {Key.QS_WORK_ADDED, WORK},
+ {Key.QS_NIGHTDISPLAY_ADDED, NIGHT},
+ };
+
+ private final ArraySet<String> mAutoAdded;
+ private final Context mContext;
+
+ public AutoAddTracker(Context context) {
+ mContext = context;
+ mAutoAdded = new ArraySet<>(getAdded());
+ for (String[] convertPref : CONVERT_PREFS) {
+ if (Prefs.getBoolean(context, convertPref[0], false)) {
+ setTileAdded(convertPref[1]);
+ Prefs.putBoolean(context, convertPref[0], false);
+ }
+ }
+ mContext.getContentResolver().registerContentObserver(
+ Secure.getUriFor(Secure.QS_AUTO_ADDED_TILES), false, mObserver);
+ }
+
+ public boolean isAdded(String tile) {
+ return mAutoAdded.contains(tile);
+ }
+
+ public void setTileAdded(String tile) {
+ if (mAutoAdded.add(tile)) {
+ saveTiles();
+ }
+ }
+
+ public void destroy() {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ }
+
+ private void saveTiles() {
+ Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES,
+ TextUtils.join(",", mAutoAdded));
+ }
+
+ private Collection<String> getAdded() {
+ String current = Secure.getString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES);
+ if (current == null) {
+ return Collections.emptyList();
+ }
+ return Arrays.asList(current.split(","));
+ }
+
+ @VisibleForTesting
+ protected final ContentObserver mObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mAutoAdded.addAll(getAdded());
+ }
+ };
+}
import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.Prefs.Key;
+import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.SecureSetting;
import com.android.systemui.statusbar.policy.DataSaverController;
*/
public class AutoTileManager {
+ public static final String HOTSPOT = "hotspot";
+ public static final String SAVER = "saver";
+ public static final String INVERSION = "inversion";
+ public static final String WORK = "work";
+ public static final String NIGHT = "night";
private final Context mContext;
private final QSTileHost mHost;
private final Handler mHandler;
+ private final AutoAddTracker mAutoTracker;
public AutoTileManager(Context context, QSTileHost host) {
+ mAutoTracker = new AutoAddTracker(context);
mContext = context;
mHost = host;
mHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
- if (!Prefs.getBoolean(context, Key.QS_HOTSPOT_ADDED, false)) {
+ if (!mAutoTracker.isAdded(HOTSPOT)) {
Dependency.get(HotspotController.class).addCallback(mHotspotCallback);
}
- if (!Prefs.getBoolean(context, Key.QS_DATA_SAVER_ADDED, false)) {
+ if (!mAutoTracker.isAdded(SAVER)) {
Dependency.get(DataSaverController.class).addCallback(mDataSaverListener);
}
- if (!Prefs.getBoolean(context, Key.QS_INVERT_COLORS_ADDED, false)) {
+ if (!mAutoTracker.isAdded(INVERSION)) {
mColorsSetting = new SecureSetting(mContext, mHandler,
Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
@Override
protected void handleValueChanged(int value, boolean observedChange) {
+ if (mAutoTracker.isAdded(INVERSION)) return;
if (value != 0) {
- mHost.addTile("inversion");
- Prefs.putBoolean(mContext, Key.QS_INVERT_COLORS_ADDED, true);
+ mHost.addTile(INVERSION);
+ mAutoTracker.setTileAdded(INVERSION);
mHandler.post(() -> mColorsSetting.setListening(false));
}
}
};
mColorsSetting.setListening(true);
}
- if (!Prefs.getBoolean(context, Key.QS_WORK_ADDED, false)) {
+ if (!mAutoTracker.isAdded(WORK)) {
Dependency.get(ManagedProfileController.class).addCallback(mProfileCallback);
}
- if (!Prefs.getBoolean(context, Key.QS_NIGHTDISPLAY_ADDED, false)
+ if (!mAutoTracker.isAdded(NIGHT)
&& NightDisplayController.isAvailable(mContext)) {
Dependency.get(NightDisplayController.class).setListener(mNightDisplayCallback);
}
public void destroy() {
mColorsSetting.setListening(false);
+ mAutoTracker.destroy();
Dependency.get(HotspotController.class).removeCallback(mHotspotCallback);
Dependency.get(DataSaverController.class).removeCallback(mDataSaverListener);
Dependency.get(ManagedProfileController.class).removeCallback(mProfileCallback);
new ManagedProfileController.Callback() {
@Override
public void onManagedProfileChanged() {
+ if (mAutoTracker.isAdded(WORK)) return;
if (Dependency.get(ManagedProfileController.class).hasActiveProfile()) {
- mHost.addTile("work");
- Prefs.putBoolean(mContext, Key.QS_WORK_ADDED, true);
+ mHost.addTile(WORK);
+ mAutoTracker.setTileAdded(WORK);
mHandler.post(() -> Dependency.get(ManagedProfileController.class)
.removeCallback(mProfileCallback));
}
private final DataSaverController.Listener mDataSaverListener = new Listener() {
@Override
public void onDataSaverChanged(boolean isDataSaving) {
+ if (mAutoTracker.isAdded(SAVER)) return;
if (isDataSaving) {
- mHost.addTile("saver");
- Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true);
+ mHost.addTile(SAVER);
+ mAutoTracker.setTileAdded(SAVER);
mHandler.post(() -> Dependency.get(DataSaverController.class).removeCallback(
mDataSaverListener));
}
private final HotspotController.Callback mHotspotCallback = new Callback() {
@Override
public void onHotspotChanged(boolean enabled) {
+ if (mAutoTracker.isAdded(HOTSPOT)) return;
if (enabled) {
- mHost.addTile("hotspot");
- Prefs.putBoolean(mContext, Key.QS_HOTSPOT_ADDED, true);
+ mHost.addTile(HOTSPOT);
+ mAutoTracker.setTileAdded(HOTSPOT);
mHandler.post(() -> Dependency.get(HotspotController.class)
.removeCallback(mHotspotCallback));
}
}
private void addNightTile() {
- mHost.addTile("night");
- Prefs.putBoolean(mContext, Key.QS_NIGHTDISPLAY_ADDED, true);
+ if (mAutoTracker.isAdded(NIGHT)) return;
+ mHost.addTile(NIGHT);
+ mAutoTracker.setTileAdded(NIGHT);
mHandler.post(() -> Dependency.get(NightDisplayController.class)
.setListener(null));
}
--- /dev/null
+/*
+ * 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.qs;
+
+import static com.android.systemui.statusbar.phone.AutoTileManager.INVERSION;
+import static com.android.systemui.statusbar.phone.AutoTileManager.SAVER;
+import static com.android.systemui.statusbar.phone.AutoTileManager.WORK;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.provider.Settings.Secure;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class AutoAddTrackerTest extends SysuiTestCase {
+
+ private AutoAddTracker mAutoTracker;
+
+ @Test
+ public void testMigration() {
+ Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true);
+ Prefs.putBoolean(mContext, Key.QS_WORK_ADDED, true);
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertTrue(mAutoTracker.isAdded(SAVER));
+ assertTrue(mAutoTracker.isAdded(WORK));
+ assertFalse(mAutoTracker.isAdded(INVERSION));
+
+ assertFalse(Prefs.getBoolean(mContext, Key.QS_DATA_SAVER_ADDED, false));
+ assertFalse(Prefs.getBoolean(mContext, Key.QS_WORK_ADDED, false));
+
+ mAutoTracker.destroy();
+ }
+
+ @Test
+ public void testChangeFromBackup() {
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertFalse(mAutoTracker.isAdded(SAVER));
+
+ Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES, SAVER);
+ mAutoTracker.mObserver.onChange(false);
+
+ assertTrue(mAutoTracker.isAdded(SAVER));
+
+ mAutoTracker.destroy();
+ }
+
+ @Test
+ public void testSetAdded() {
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertFalse(mAutoTracker.isAdded(SAVER));
+ mAutoTracker.setTileAdded(SAVER);
+
+ assertTrue(mAutoTracker.isAdded(SAVER));
+
+ mAutoTracker.destroy();
+ }
+
+ @Test
+ public void testPersist() {
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertFalse(mAutoTracker.isAdded(SAVER));
+ mAutoTracker.setTileAdded(SAVER);
+
+ mAutoTracker.destroy();
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertTrue(mAutoTracker.isAdded(SAVER));
+
+ mAutoTracker.destroy();
+ }
+
+}
\ No newline at end of file