Files
packages_apps_Settings/src/com/android/settings/dashboard/conditional/ConditionManager.java
Salvador Martinez 179e16445e Added logging to pinpoint source of bug
Sometimes the airplane mode banner will show up even
though airplane mode is not on. Logging has been added
to several areas around this condition in addition to
where the actual view is created. This will be used
to try and get a better handle on what the source of
the bug is.

Test: manual
Bug: 30860132
Change-Id: I7213aa7e187c5a8c0e94a5ce7a3269e6667cd61b
2016-12-05 15:32:14 -08:00

275 lines
9.8 KiB
Java

/*
* 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.
*/
package com.android.settings.dashboard.conditional;
import android.content.Context;
import android.os.AsyncTask;
import android.os.PersistableBundle;
import android.util.Log;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ConditionManager {
private static final String TAG = "ConditionManager";
private static final boolean DEBUG = false;
private static final String PKG = "com.android.settings.dashboard.conditional.";
private static final String FILE_NAME = "condition_state.xml";
private static final String TAG_CONDITIONS = "cs";
private static final String TAG_CONDITION = "c";
private static final String ATTR_CLASS = "cls";
private static ConditionManager sInstance;
private final Context mContext;
private final ArrayList<Condition> mConditions;
private File mXmlFile;
private final ArrayList<ConditionListener> mListeners = new ArrayList<>();
private ConditionManager(Context context, boolean loadConditionsNow) {
mContext = context;
mConditions = new ArrayList<>();
if (loadConditionsNow) {
Log.d(TAG, "conditions loading synchronously");
ConditionLoader loader = new ConditionLoader();
loader.onPostExecute(loader.doInBackground());
} else {
Log.d(TAG, "conditions loading asychronously");
new ConditionLoader().execute();
}
}
public void refreshAll() {
final int N = mConditions.size();
for (int i = 0; i < N; i++) {
mConditions.get(i).refreshState();
}
}
private void readFromXml(File xmlFile, ArrayList<Condition> conditions) {
if (DEBUG) Log.d(TAG, "Reading from " + xmlFile.toString());
try {
XmlPullParser parser = Xml.newPullParser();
FileReader in = new FileReader(xmlFile);
parser.setInput(in);
int state = parser.getEventType();
while (state != XmlPullParser.END_DOCUMENT) {
if (TAG_CONDITION.equals(parser.getName())) {
int depth = parser.getDepth();
String clz = parser.getAttributeValue("", ATTR_CLASS);
if (!clz.startsWith(PKG)) {
clz = PKG + clz;
}
Condition condition = createCondition(Class.forName(clz));
PersistableBundle bundle = PersistableBundle.restoreFromXml(parser);
if (DEBUG) Log.d(TAG, "Reading " + clz + " -- " + bundle);
condition.restoreState(bundle);
conditions.add(condition);
while (parser.getDepth() > depth) {
parser.next();
}
}
state = parser.next();
}
in.close();
} catch (XmlPullParserException | IOException | ClassNotFoundException e) {
Log.w(TAG, "Problem reading " + FILE_NAME, e);
}
}
private void saveToXml() {
if (DEBUG) Log.d(TAG, "Writing to " + mXmlFile.toString());
try {
XmlSerializer serializer = Xml.newSerializer();
FileWriter writer = new FileWriter(mXmlFile);
serializer.setOutput(writer);
serializer.startDocument("UTF-8", true);
serializer.startTag("", TAG_CONDITIONS);
final int N = mConditions.size();
for (int i = 0; i < N; i++) {
PersistableBundle bundle = new PersistableBundle();
if (mConditions.get(i).saveState(bundle)) {
serializer.startTag("", TAG_CONDITION);
final String clz = mConditions.get(i).getClass().getSimpleName();
serializer.attribute("", ATTR_CLASS, clz);
bundle.saveToXml(serializer);
serializer.endTag("", TAG_CONDITION);
}
}
serializer.endTag("", TAG_CONDITIONS);
serializer.flush();
writer.close();
} catch (XmlPullParserException | IOException e) {
Log.w(TAG, "Problem writing " + FILE_NAME, e);
}
}
private void addMissingConditions(ArrayList<Condition> conditions) {
addIfMissing(AirplaneModeCondition.class, conditions);
addIfMissing(HotspotCondition.class, conditions);
addIfMissing(DndCondition.class, conditions);
addIfMissing(BatterySaverCondition.class, conditions);
addIfMissing(CellularDataCondition.class, conditions);
addIfMissing(BackgroundDataCondition.class, conditions);
addIfMissing(WorkModeCondition.class, conditions);
addIfMissing(NightDisplayCondition.class, conditions);
Collections.sort(conditions, CONDITION_COMPARATOR);
}
private void addIfMissing(Class<? extends Condition> clz, ArrayList<Condition> conditions) {
if (getCondition(clz, conditions) == null) {
if (DEBUG) Log.d(TAG, "Adding missing " + clz.getName());
conditions.add(createCondition(clz));
}
}
private Condition createCondition(Class<?> clz) {
if (AirplaneModeCondition.class == clz) {
return new AirplaneModeCondition(this);
} else if (HotspotCondition.class == clz) {
return new HotspotCondition(this);
} else if (DndCondition.class == clz) {
return new DndCondition(this);
} else if (BatterySaverCondition.class == clz) {
return new BatterySaverCondition(this);
} else if (CellularDataCondition.class == clz) {
return new CellularDataCondition(this);
} else if (BackgroundDataCondition.class == clz) {
return new BackgroundDataCondition(this);
} else if (WorkModeCondition.class == clz) {
return new WorkModeCondition(this);
} else if (NightDisplayCondition.class == clz) {
return new NightDisplayCondition(this);
}
throw new RuntimeException("Unexpected Condition " + clz);
}
Context getContext() {
return mContext;
}
public <T extends Condition> T getCondition(Class<T> clz) {
return getCondition(clz, mConditions);
}
private <T extends Condition> T getCondition(Class<T> clz, List<Condition> conditions) {
final int N = conditions.size();
for (int i = 0; i < N; i++) {
if (clz.equals(conditions.get(i).getClass())) {
return (T) conditions.get(i);
}
}
return null;
}
public List<Condition> getConditions() {
return mConditions;
}
public List<Condition> getVisibleConditions() {
List<Condition> conditions = new ArrayList<>();
final int N = mConditions.size();
for (int i = 0; i < N; i++) {
if (mConditions.get(i).shouldShow()) {
conditions.add(mConditions.get(i));
}
}
return conditions;
}
public void notifyChanged(Condition condition) {
saveToXml();
Collections.sort(mConditions, CONDITION_COMPARATOR);
final int N = mListeners.size();
for (int i = 0; i < N; i++) {
mListeners.get(i).onConditionsChanged();
}
}
public void addListener(ConditionListener listener) {
mListeners.add(listener);
listener.onConditionsChanged();
}
public void remListener(ConditionListener listener) {
mListeners.remove(listener);
}
private class ConditionLoader extends AsyncTask<Void, Void, ArrayList<Condition>> {
@Override
protected ArrayList<Condition> doInBackground(Void... params) {
Log.d(TAG, "loading conditions from xml");
ArrayList<Condition> conditions = new ArrayList<>();
mXmlFile = new File(mContext.getFilesDir(), FILE_NAME);
if (mXmlFile.exists()) {
readFromXml(mXmlFile, conditions);
}
addMissingConditions(conditions);
return conditions;
}
@Override
protected void onPostExecute(ArrayList<Condition> conditions) {
Log.d(TAG, "conditions loaded from xml, refreshing conditions");
mConditions.clear();
mConditions.addAll(conditions);
refreshAll();
}
}
public static ConditionManager get(Context context) {
return get(context, true);
}
public static ConditionManager get(Context context, boolean loadConditionsNow) {
if (sInstance == null) {
sInstance = new ConditionManager(context.getApplicationContext(), loadConditionsNow);
}
return sInstance;
}
public interface ConditionListener {
void onConditionsChanged();
}
private static final Comparator<Condition> CONDITION_COMPARATOR = new Comparator<Condition>() {
@Override
public int compare(Condition lhs, Condition rhs) {
return Long.compare(lhs.getLastChange(), rhs.getLastChange());
}
};
}