SDK sandboxes run in a separate UID range. Their network usage should be attributed to the corresponding app. Make sure we collapse the usage collection of sandboxes to the corresponding app UID in DataUsageList. For AppDataUsage, make sure we add in the sandbox UID when being asked to calculate data usage for a regular app UID. Invoke DataUsageCycleLoader with all UIDs in AppItem, because there can now be multiple UIDs associated with a regular app, too. Also make sure that all new instances of AppItem for regular applications have their own application UID. Bug: 225319220 Test: manual Change-Id: Id101a96ee4e3ba02376fa2ac64a9f9c2581acb61
164 lines
5.7 KiB
Java
164 lines
5.7 KiB
Java
/*
|
|
* Copyright (C) 2018 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.applications.appinfo;
|
|
|
|
import android.content.Context;
|
|
import android.net.NetworkStats;
|
|
import android.net.NetworkTemplate;
|
|
import android.os.Bundle;
|
|
import android.os.Process;
|
|
import android.text.format.DateUtils;
|
|
import android.text.format.Formatter;
|
|
|
|
import androidx.annotation.VisibleForTesting;
|
|
import androidx.loader.app.LoaderManager;
|
|
import androidx.loader.content.Loader;
|
|
import androidx.preference.Preference;
|
|
import androidx.preference.PreferenceScreen;
|
|
|
|
import com.android.settings.R;
|
|
import com.android.settings.SettingsPreferenceFragment;
|
|
import com.android.settings.Utils;
|
|
import com.android.settings.datausage.AppDataUsage;
|
|
import com.android.settings.datausage.DataUsageUtils;
|
|
import com.android.settingslib.AppItem;
|
|
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
|
import com.android.settingslib.core.lifecycle.events.OnPause;
|
|
import com.android.settingslib.core.lifecycle.events.OnResume;
|
|
import com.android.settingslib.net.NetworkCycleDataForUid;
|
|
import com.android.settingslib.net.NetworkCycleDataForUidLoader;
|
|
|
|
import java.util.List;
|
|
|
|
public class AppDataUsagePreferenceController extends AppInfoPreferenceControllerBase
|
|
implements LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>, LifecycleObserver,
|
|
OnResume, OnPause {
|
|
|
|
private List<NetworkCycleDataForUid> mAppUsageData;
|
|
|
|
public AppDataUsagePreferenceController(Context context, String key) {
|
|
super(context, key);
|
|
}
|
|
|
|
@Override
|
|
public int getAvailabilityStatus() {
|
|
return isBandwidthControlEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
|
}
|
|
|
|
@Override
|
|
public void displayPreference(PreferenceScreen screen) {
|
|
super.displayPreference(screen);
|
|
}
|
|
|
|
@Override
|
|
public void updateState(Preference preference) {
|
|
preference.setSummary(getDataSummary());
|
|
}
|
|
|
|
@Override
|
|
public void onResume() {
|
|
if (isAvailable()) {
|
|
final int uid = mParent.getAppEntry().info.uid;
|
|
final AppItem app = new AppItem(uid);
|
|
app.addUid(uid);
|
|
mParent.getLoaderManager().restartLoader(mParent.LOADER_CHART_DATA, null /* args */,
|
|
this);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onPause() {
|
|
if (isAvailable()) {
|
|
mParent.getLoaderManager().destroyLoader(mParent.LOADER_CHART_DATA);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
|
|
final NetworkTemplate template = getTemplate(mContext);
|
|
final int uid = mParent.getAppEntry().info.uid;
|
|
|
|
final NetworkCycleDataForUidLoader.Builder builder =
|
|
NetworkCycleDataForUidLoader.builder(mContext);
|
|
builder.setRetrieveDetail(false)
|
|
.setNetworkTemplate(template);
|
|
|
|
builder.addUid(uid);
|
|
if (Process.isApplicationUid(uid)) {
|
|
// Also add in network usage for the app's SDK sandbox
|
|
builder.addUid(Process.toSdkSandboxUid(uid));
|
|
}
|
|
return builder.build();
|
|
}
|
|
|
|
@Override
|
|
public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
|
|
List<NetworkCycleDataForUid> data) {
|
|
mAppUsageData = data;
|
|
updateState(mPreference);
|
|
}
|
|
|
|
@Override
|
|
public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
|
|
// Leave last result.
|
|
}
|
|
|
|
@Override
|
|
protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
|
|
return AppDataUsage.class;
|
|
}
|
|
|
|
private CharSequence getDataSummary() {
|
|
if (mAppUsageData != null) {
|
|
long totalBytes = 0;
|
|
long startTime = System.currentTimeMillis();
|
|
for (NetworkCycleDataForUid data : mAppUsageData) {
|
|
totalBytes += data.getTotalUsage();
|
|
final long cycleStart = data.getStartTime();
|
|
if (cycleStart < startTime) {
|
|
startTime = cycleStart;
|
|
}
|
|
}
|
|
if (totalBytes == 0) {
|
|
return mContext.getString(R.string.no_data_usage);
|
|
}
|
|
return mContext.getString(R.string.data_summary_format,
|
|
Formatter.formatFileSize(mContext, totalBytes, Formatter.FLAG_IEC_UNITS),
|
|
DateUtils.formatDateTime(mContext, startTime,
|
|
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH));
|
|
}
|
|
return mContext.getString(R.string.computing_size);
|
|
}
|
|
|
|
private static NetworkTemplate getTemplate(Context context) {
|
|
if (DataUsageUtils.hasReadyMobileRadio(context)) {
|
|
return new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE).setMeteredness(
|
|
NetworkStats.METERED_YES).build();
|
|
}
|
|
if (DataUsageUtils.hasWifiRadio(context)) {
|
|
return new NetworkTemplate.Builder(NetworkTemplate.MATCH_WIFI).build();
|
|
}
|
|
return new NetworkTemplate.Builder(NetworkTemplate.MATCH_ETHERNET).build();
|
|
}
|
|
|
|
@VisibleForTesting
|
|
boolean isBandwidthControlEnabled() {
|
|
return Utils.isBandwidthControlEnabled();
|
|
}
|
|
|
|
}
|