An async task was trying to get the context
in an InstrumentedFragment. This could return
null if the context disappears before the new
thread gets to that line. Logging will now
be aborted if context is null to avoid this.
Test: Manual/Monkey Stability Test
Bug: 31058928
Change-Id: Iae97d389e58a76b0f213a2749415501894ebf649
(cherry picked from commit 566b66e27c
)
270 lines
11 KiB
Java
270 lines
11 KiB
Java
/*
|
|
* Copyright (C) 2014 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;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.os.AsyncTask;
|
|
import android.os.Bundle;
|
|
import android.support.v7.widget.LinearLayoutManager;
|
|
import android.util.Log;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
|
|
import com.android.internal.logging.MetricsLogger;
|
|
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
|
import com.android.settings.InstrumentedFragment;
|
|
import com.android.settings.R;
|
|
import com.android.settings.Settings;
|
|
import com.android.settings.SettingsActivity;
|
|
import com.android.settings.dashboard.conditional.Condition;
|
|
import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
|
|
import com.android.settings.dashboard.conditional.ConditionManager;
|
|
import com.android.settings.dashboard.conditional.FocusRecyclerView;
|
|
import com.android.settingslib.HelpUtils;
|
|
import com.android.settingslib.SuggestionParser;
|
|
import com.android.settingslib.drawer.DashboardCategory;
|
|
import com.android.settingslib.drawer.SettingsDrawerActivity;
|
|
import com.android.settingslib.drawer.Tile;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
public class DashboardSummary extends InstrumentedFragment
|
|
implements SettingsDrawerActivity.CategoryListener, ConditionManager.ConditionListener,
|
|
FocusRecyclerView.FocusListener {
|
|
public static final boolean DEBUG = false;
|
|
private static final boolean DEBUG_TIMING = false;
|
|
private static final String TAG = "DashboardSummary";
|
|
|
|
public static final String[] INITIAL_ITEMS = new String[] {
|
|
Settings.WifiSettingsActivity.class.getName(),
|
|
Settings.BluetoothSettingsActivity.class.getName(),
|
|
Settings.DataUsageSummaryActivity.class.getName(),
|
|
Settings.PowerUsageSummaryActivity.class.getName(),
|
|
Settings.ManageApplicationsActivity.class.getName(),
|
|
Settings.StorageSettingsActivity.class.getName(),
|
|
};
|
|
|
|
private static final String SUGGESTIONS = "suggestions";
|
|
|
|
private static final String EXTRA_SCROLL_POSITION = "scroll_position";
|
|
private static final String EXTRA_SUGGESTION_SHOWN_LOGGED = "suggestions_shown_logged";
|
|
private static final String EXTRA_SUGGESTION_HIDDEN_LOGGED = "suggestions_hidden_logged";
|
|
|
|
private FocusRecyclerView mDashboard;
|
|
private DashboardAdapter mAdapter;
|
|
private SummaryLoader mSummaryLoader;
|
|
private ConditionManager mConditionManager;
|
|
private SuggestionParser mSuggestionParser;
|
|
private LinearLayoutManager mLayoutManager;
|
|
private SuggestionsChecks mSuggestionsChecks;
|
|
private ArrayList<String> mSuggestionsShownLogged;
|
|
private ArrayList<String> mSuggestionsHiddenLogged;
|
|
|
|
@Override
|
|
protected int getMetricsCategory() {
|
|
return MetricsEvent.DASHBOARD_SUMMARY;
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
long startTime = System.currentTimeMillis();
|
|
super.onCreate(savedInstanceState);
|
|
|
|
List<DashboardCategory> categories =
|
|
((SettingsActivity) getActivity()).getDashboardCategories();
|
|
mSummaryLoader = new SummaryLoader(getActivity(), categories);
|
|
Context context = getContext();
|
|
mConditionManager = ConditionManager.get(context, false);
|
|
mSuggestionParser = new SuggestionParser(context,
|
|
context.getSharedPreferences(SUGGESTIONS, 0), R.xml.suggestion_ordering);
|
|
mSuggestionsChecks = new SuggestionsChecks(getContext());
|
|
if (savedInstanceState == null) {
|
|
mSuggestionsShownLogged = new ArrayList<>();
|
|
mSuggestionsHiddenLogged = new ArrayList<>();
|
|
} else {
|
|
mSuggestionsShownLogged =
|
|
savedInstanceState.getStringArrayList(EXTRA_SUGGESTION_SHOWN_LOGGED);
|
|
mSuggestionsHiddenLogged =
|
|
savedInstanceState.getStringArrayList(EXTRA_SUGGESTION_HIDDEN_LOGGED);
|
|
}
|
|
if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
|
|
+ " ms");
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
mSummaryLoader.release();
|
|
super.onDestroy();
|
|
}
|
|
|
|
@Override
|
|
public void onStart() {
|
|
long startTime = System.currentTimeMillis();
|
|
super.onStart();
|
|
|
|
((SettingsDrawerActivity) getActivity()).addCategoryListener(this);
|
|
mSummaryLoader.setListening(true);
|
|
for (Condition c : mConditionManager.getConditions()) {
|
|
if (c.shouldShow()) {
|
|
MetricsLogger.visible(getContext(), c.getMetricsConstant());
|
|
}
|
|
}
|
|
if (DEBUG_TIMING) Log.d(TAG, "onStart took " + (System.currentTimeMillis() - startTime)
|
|
+ " ms");
|
|
}
|
|
|
|
@Override
|
|
public void onStop() {
|
|
super.onStop();
|
|
|
|
((SettingsDrawerActivity) getActivity()).remCategoryListener(this);
|
|
mSummaryLoader.setListening(false);
|
|
for (Condition c : mConditionManager.getConditions()) {
|
|
if (c.shouldShow()) {
|
|
MetricsLogger.hidden(getContext(), c.getMetricsConstant());
|
|
}
|
|
}
|
|
if (mAdapter.getSuggestions() == null) {
|
|
return;
|
|
}
|
|
if (!getActivity().isChangingConfigurations()) {
|
|
for (Tile suggestion : mAdapter.getSuggestions()) {
|
|
String id = DashboardAdapter.getSuggestionIdentifier(getContext(), suggestion);
|
|
if (!mSuggestionsHiddenLogged.contains(id)) {
|
|
mSuggestionsHiddenLogged.add(id);
|
|
MetricsLogger.action(getContext(),
|
|
MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onWindowFocusChanged(boolean hasWindowFocus) {
|
|
long startTime = System.currentTimeMillis();
|
|
if (hasWindowFocus) {
|
|
mConditionManager.addListener(this);
|
|
mConditionManager.refreshAll();
|
|
} else {
|
|
mConditionManager.remListener(this);
|
|
}
|
|
if (DEBUG_TIMING) Log.d(TAG, "onWindowFocusChanged took "
|
|
+ (System.currentTimeMillis() - startTime) + " ms");
|
|
}
|
|
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
Bundle savedInstanceState) {
|
|
return inflater.inflate(R.layout.dashboard, container, false);
|
|
}
|
|
|
|
@Override
|
|
public void onSaveInstanceState(Bundle outState) {
|
|
super.onSaveInstanceState(outState);
|
|
if (mLayoutManager == null) return;
|
|
outState.putInt(EXTRA_SCROLL_POSITION, mLayoutManager.findFirstVisibleItemPosition());
|
|
if (mAdapter != null) {
|
|
mAdapter.onSaveInstanceState(outState);
|
|
}
|
|
outState.putStringArrayList(EXTRA_SUGGESTION_HIDDEN_LOGGED, mSuggestionsHiddenLogged);
|
|
outState.putStringArrayList(EXTRA_SUGGESTION_SHOWN_LOGGED, mSuggestionsShownLogged);
|
|
}
|
|
|
|
@Override
|
|
public void onViewCreated(View view, Bundle bundle) {
|
|
long startTime = System.currentTimeMillis();
|
|
mDashboard = (FocusRecyclerView) view.findViewById(R.id.dashboard_container);
|
|
mLayoutManager = new LinearLayoutManager(getContext());
|
|
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
|
|
if (bundle != null) {
|
|
int scrollPosition = bundle.getInt(EXTRA_SCROLL_POSITION);
|
|
mLayoutManager.scrollToPosition(scrollPosition);
|
|
}
|
|
mDashboard.setLayoutManager(mLayoutManager);
|
|
mDashboard.setHasFixedSize(true);
|
|
mDashboard.setListener(this);
|
|
mDashboard.addItemDecoration(new DashboardDecorator(getContext()));
|
|
mAdapter = new DashboardAdapter(getContext(), mSuggestionParser, bundle,
|
|
mConditionManager.getConditions());
|
|
mDashboard.setAdapter(mAdapter);
|
|
mSummaryLoader.setAdapter(mAdapter);
|
|
ConditionAdapterUtils.addDismiss(mDashboard);
|
|
if (DEBUG_TIMING) Log.d(TAG, "onViewCreated took "
|
|
+ (System.currentTimeMillis() - startTime) + " ms");
|
|
rebuildUI();
|
|
}
|
|
|
|
private void rebuildUI() {
|
|
if (!isAdded()) {
|
|
Log.w(TAG, "Cannot build the DashboardSummary UI yet as the Fragment is not added");
|
|
return;
|
|
}
|
|
|
|
// recheck to see if any suggestions have been changed.
|
|
new SuggestionLoader().execute();
|
|
}
|
|
|
|
@Override
|
|
public void onCategoriesChanged() {
|
|
rebuildUI();
|
|
}
|
|
|
|
@Override
|
|
public void onConditionsChanged() {
|
|
Log.d(TAG, "onConditionsChanged");
|
|
mAdapter.setConditions(mConditionManager.getConditions());
|
|
}
|
|
|
|
private class SuggestionLoader extends AsyncTask<Void, Void, List<Tile>> {
|
|
|
|
@Override
|
|
protected List<Tile> doInBackground(Void... params) {
|
|
final Context context = getContext();
|
|
List<Tile> suggestions = mSuggestionParser.getSuggestions();
|
|
for (int i = 0; i < suggestions.size(); i++) {
|
|
Tile suggestion = suggestions.get(i);
|
|
if (mSuggestionsChecks.isSuggestionComplete(suggestion)) {
|
|
mAdapter.disableSuggestion(suggestion);
|
|
suggestions.remove(i--);
|
|
} else if (context != null) {
|
|
String id = DashboardAdapter.getSuggestionIdentifier(context, suggestion);
|
|
if (!mSuggestionsShownLogged.contains(id)) {
|
|
mSuggestionsShownLogged.add(id);
|
|
MetricsLogger.action(context,
|
|
MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, id);
|
|
}
|
|
}
|
|
}
|
|
return suggestions;
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(List<Tile> tiles) {
|
|
final Activity activity = getActivity();
|
|
if (activity == null) {
|
|
return;
|
|
}
|
|
List<DashboardCategory> categories =
|
|
((SettingsActivity) activity).getDashboardCategories();
|
|
mAdapter.setCategoriesAndSuggestions(categories, tiles);
|
|
}
|
|
}
|
|
}
|