Listen to mobile data enabled flag change.

The listener is necessary to show/hide the gear icon on top of billing
cycle settings screen as user turn on/off mobile data from QS.

code cleanup: remove dividedCategory

Fix: 28066849
Test: make RunSettinsgRoboTests

Change-Id: I3b7075512042127fd711a8a70a572adfed069502
This commit is contained in:
Fan Zhang
2017-03-16 12:50:44 -07:00
parent d764c57dcc
commit 917721c8d6
6 changed files with 128 additions and 89 deletions

View File

@@ -44,7 +44,7 @@
</intent> </intent>
</Preference> </Preference>
<com.android.settings.DividedCategory <PreferenceCategory
android:key="recent_location_requests" android:key="recent_location_requests"
android:title="@string/location_category_recent_location_requests" /> android:title="@string/location_category_recent_location_requests" />

View File

@@ -1,36 +0,0 @@
/*
* Copyright (C) 2016 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;
import android.content.Context;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
/**
* PreferenceCategory that allows a divider above it.
*/
public class DividedCategory extends PreferenceCategory {
public DividedCategory(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
holder.setDividerAllowedAbove(true);
}
}

View File

@@ -58,8 +58,9 @@ public class BillingCyclePreference extends Preference implements TemplatePrefer
mSubId = subId; mSubId = subId;
mServices = services; mServices = services;
mPolicy = services.mPolicyEditor.getPolicy(mTemplate); mPolicy = services.mPolicyEditor.getPolicy(mTemplate);
setSummary(getContext().getString(R.string.billing_cycle_fragment_summary, setSummary(getContext().getString(R.string.billing_cycle_fragment_summary, mPolicy != null
mPolicy != null ? mPolicy.cycleDay : 1)); ? mPolicy.cycleDay
: "1"));
setIntent(getIntent()); setIntent(getIntent());
} }

View File

@@ -46,8 +46,10 @@ import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener; import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Spinner; import android.widget.Spinner;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.datausage.CycleAdapter.SpinnerInterface;
import com.android.settingslib.AppItem; import com.android.settingslib.AppItem;
import com.android.settingslib.net.ChartData; import com.android.settingslib.net.ChartData;
import com.android.settingslib.net.ChartDataLoader; import com.android.settingslib.net.ChartDataLoader;
@@ -56,9 +58,7 @@ import com.android.settingslib.net.UidDetailProvider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
@@ -73,6 +73,10 @@ import static com.android.settings.datausage.DataUsageSummary.TEST_RADIOS_PROP;
* to inspect based on usage cycle and control through {@link NetworkPolicy}. * to inspect based on usage cycle and control through {@link NetworkPolicy}.
*/ */
public class DataUsageList extends DataUsageBase { public class DataUsageList extends DataUsageBase {
public static final String EXTRA_SUB_ID = "sub_id";
public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
private static final String TAG = "DataUsage"; private static final String TAG = "DataUsage";
private static final boolean LOGD = false; private static final boolean LOGD = false;
@@ -82,8 +86,14 @@ public class DataUsageList extends DataUsageBase {
private static final int LOADER_CHART_DATA = 2; private static final int LOADER_CHART_DATA = 2;
private static final int LOADER_SUMMARY = 3; private static final int LOADER_SUMMARY = 3;
public static final String EXTRA_SUB_ID = "sub_id";
public static final String EXTRA_NETWORK_TEMPLATE = "network_template"; private final CellDataPreference.DataStateListener mDataStateListener =
new CellDataPreference.DataStateListener() {
@Override
public void onChange(boolean selfChange) {
updatePolicy();
}
};
private INetworkStatsSession mStatsSession; private INetworkStatsSession mStatsSession;
@@ -93,15 +103,7 @@ public class DataUsageList extends DataUsageBase {
private int mSubId; private int mSubId;
private ChartData mChartData; private ChartData mChartData;
/** Flag used to ignore listeners during binding. */
private boolean mBinding;
private UidDetailProvider mUidDetailProvider; private UidDetailProvider mUidDetailProvider;
/**
* Local cache of data enabled for subId, used to work around delays.
*/
private final Map<String, Boolean> mMobileDataEnabled = new HashMap<String, Boolean>();
private CycleAdapter mCycleAdapter; private CycleAdapter mCycleAdapter;
private Spinner mCycleSpinner; private Spinner mCycleSpinner;
private Preference mUsageAmount; private Preference mUsageAmount;
@@ -146,9 +148,14 @@ public class DataUsageList extends DataUsageBase {
super.onViewCreated(v, savedInstanceState); super.onViewCreated(v, savedInstanceState);
mHeader = setPinnedHeaderView(R.layout.apps_filter_spinner); mHeader = setPinnedHeaderView(R.layout.apps_filter_spinner);
mCycleSpinner = (Spinner) mHeader.findViewById(R.id.filter_spinner); mHeader.findViewById(R.id.filter_settings).setOnClickListener(btn -> {
mCycleAdapter = new CycleAdapter(mCycleSpinner.getContext(), final Bundle args = new Bundle();
new CycleAdapter.SpinnerInterface() { args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
startFragment(DataUsageList.this, BillingCycleSettings.class.getName(),
R.string.billing_cycle, 0, args);
});
mCycleSpinner = mHeader.findViewById(R.id.filter_spinner);
mCycleAdapter = new CycleAdapter(mCycleSpinner.getContext(), new SpinnerInterface() {
@Override @Override
public void setAdapter(CycleAdapter cycleAdapter) { public void setAdapter(CycleAdapter cycleAdapter) {
mCycleSpinner.setAdapter(cycleAdapter); mCycleSpinner.setAdapter(cycleAdapter);
@@ -175,7 +182,7 @@ public class DataUsageList extends DataUsageBase {
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
mDataStateListener.setListener(true, mSubId, getContext());
updateBody(); updateBody();
// kick off background task to update stats // kick off background task to update stats
@@ -201,6 +208,12 @@ public class DataUsageList extends DataUsageBase {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} }
@Override
public void onPause() {
super.onPause();
mDataStateListener.setListener(false, mSubId, getContext());
}
@Override @Override
public void onDestroy() { public void onDestroy() {
mUidDetailProvider.clearCache(); mUidDetailProvider.clearCache();
@@ -217,7 +230,6 @@ public class DataUsageList extends DataUsageBase {
* binds them to visible controls. * binds them to visible controls.
*/ */
private void updateBody() { private void updateBody() {
mBinding = true;
if (!isAdded()) return; if (!isAdded()) return;
final Context context = getActivity(); final Context context = getActivity();
@@ -231,10 +243,8 @@ public class DataUsageList extends DataUsageBase {
// detail mode can change visible menus, invalidate // detail mode can change visible menus, invalidate
getActivity().invalidateOptionsMenu(); getActivity().invalidateOptionsMenu();
mBinding = false;
int seriesColor = context.getColor(R.color.sim_noitification); int seriesColor = context.getColor(R.color.sim_noitification);
if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID){ if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final SubscriptionInfo sir = services.mSubscriptionManager final SubscriptionInfo sir = services.mSubscriptionManager
.getActiveSubscriptionInfo(mSubId); .getActiveSubscriptionInfo(mSubId);
@@ -252,33 +262,22 @@ public class DataUsageList extends DataUsageBase {
* Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for * Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
* current {@link #mTemplate}. * current {@link #mTemplate}.
*/ */
private void updatePolicy(boolean refreshCycle) { private void updatePolicy() {
final NetworkPolicy policy = services.mPolicyEditor.getPolicy(mTemplate); final NetworkPolicy policy = services.mPolicyEditor.getPolicy(mTemplate);
final View configureButton = mHeader.findViewById(R.id.filter_settings);
//SUB SELECT //SUB SELECT
if (isNetworkPolicyModifiable(policy, mSubId) && isMobileDataAvailable(mSubId)) { if (isNetworkPolicyModifiable(policy, mSubId) && isMobileDataAvailable(mSubId)) {
mChart.setNetworkPolicy(policy); mChart.setNetworkPolicy(policy);
mHeader.findViewById(R.id.filter_settings).setVisibility(View.VISIBLE); configureButton.setVisibility(View.VISIBLE);
mHeader.findViewById(R.id.filter_settings).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle args = new Bundle();
args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
startFragment(DataUsageList.this, BillingCycleSettings.class.getName(),
R.string.billing_cycle, 0, args);
}
});
} else { } else {
// controls are disabled; don't bind warning/limit sweeps // controls are disabled; don't bind warning/limit sweeps
mChart.setNetworkPolicy(null); mChart.setNetworkPolicy(null);
mHeader.findViewById(R.id.filter_settings).setVisibility(View.GONE); configureButton.setVisibility(View.GONE);
} }
if (refreshCycle) { // generate cycle list based on policy and available history
// generate cycle list based on policy and available history if (mCycleAdapter.updateCycleList(policy, mChartData)) {
if (mCycleAdapter.updateCycleList(policy, mChartData)) { updateDetailData();
updateDetailData();
}
} }
} }
@@ -413,9 +412,10 @@ public class DataUsageList extends DataUsageBase {
/** /**
* Accumulate data usage of a network stats entry for the item mapped by the collapse key. * Accumulate data usage of a network stats entry for the item mapped by the collapse key.
* Creates the item if needed. * Creates the item if needed.
* @param collapseKey the collapse key used to map the item. *
* @param knownItems collection of known (already existing) items. * @param collapseKey the collapse key used to map the item.
* @param entry the network stats entry to extract data usage from. * @param knownItems collection of known (already existing) items.
* @param entry the network stats entry to extract data usage from.
* @param itemCategory the item is categorized on the list view by this category. Must be * @param itemCategory the item is categorized on the list view by this category. Must be
*/ */
private static long accumulate(int collapseKey, final SparseArray<AppItem> knownItems, private static long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
@@ -461,7 +461,7 @@ public class DataUsageList extends DataUsageBase {
if (LOGD) { if (LOGD) {
Log.d(TAG, "hasReadyMobileRadio:" Log.d(TAG, "hasReadyMobileRadio:"
+ " conn.isNetworkSupported(TYPE_MOBILE)=" + " conn.isNetworkSupported(TYPE_MOBILE)="
+ conn.isNetworkSupported(TYPE_MOBILE) + conn.isNetworkSupported(TYPE_MOBILE)
+ " isReady=" + isReady); + " isReady=" + isReady);
} }
return retVal; return retVal;
@@ -480,10 +480,13 @@ public class DataUsageList extends DataUsageBase {
final int slotId = SubscriptionManager.getSlotId(subId); final int slotId = SubscriptionManager.getSlotId(subId);
final boolean isReady = tele.getSimState(slotId) == SIM_STATE_READY; final boolean isReady = tele.getSimState(slotId) == SIM_STATE_READY;
boolean retVal = conn.isNetworkSupported(TYPE_MOBILE) && isReady; boolean retVal = conn.isNetworkSupported(TYPE_MOBILE) && isReady;
if (LOGD) Log.d(TAG, "hasReadyMobileRadio: subId=" + subId if (LOGD) {
+ " conn.isNetworkSupported(TYPE_MOBILE)=" + conn.isNetworkSupported(TYPE_MOBILE) Log.d(TAG, "hasReadyMobileRadio: subId=" + subId
+ " isReady=" + isReady); + " conn.isNetworkSupported(TYPE_MOBILE)="
+ conn.isNetworkSupported(TYPE_MOBILE)
+ " isReady=" + isReady);
}
return retVal; return retVal;
} }
@@ -524,8 +527,8 @@ public class DataUsageList extends DataUsageBase {
mChartData = data; mChartData = data;
mChart.setNetworkStats(mChartData.network); mChart.setNetworkStats(mChartData.network);
// calcuate policy cycles based on available data // calculate policy cycles based on available data
updatePolicy(true); updatePolicy();
} }
@Override @Override

View File

@@ -17,10 +17,10 @@ package com.android.settings.datausage;
import android.content.Context; import android.content.Context;
import android.net.NetworkTemplate; import android.net.NetworkTemplate;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.util.AttributeSet; import android.util.AttributeSet;
import com.android.settings.DividedCategory;
public class TemplatePreferenceCategory extends DividedCategory implements TemplatePreference { public class TemplatePreferenceCategory extends PreferenceCategory implements TemplatePreference {
private NetworkTemplate mTemplate; private NetworkTemplate mTemplate;
private int mSubId; private int mSubId;

View File

@@ -0,0 +1,71 @@
/*
* 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.settings.datausage;
import android.content.Context;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settingslib.NetworkPolicyEditor;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class DataUsageListTest {
@Mock
private CellDataPreference.DataStateListener mListener;
@Mock
private TemplatePreference.NetworkServices mNetworkServices;
@Mock
private Context mContext;
private DataUsageList mDataUsageList;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mNetworkServices.mPolicyEditor = mock(NetworkPolicyEditor.class);
mDataUsageList = spy(DataUsageList.class);
doReturn(mContext).when(mDataUsageList).getContext();
ReflectionHelpers.setField(mDataUsageList, "mDataStateListener", mListener);
ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
}
@Test
public void resumePause_shouldListenUnlistenDataStateChange() {
mDataUsageList.onResume();
verify(mListener).setListener(true, 0, mContext);
mDataUsageList.onPause();
verify(mListener).setListener(false, 0, mContext);
}
}