Snap for 8519467 from 5ef52de6b2 to tm-release

Change-Id: I6a764e2b046ad2965b06d00ee391ec80e03551aa
This commit is contained in:
Android Build Coastguard Worker
2022-04-30 01:09:23 +00:00
19 changed files with 301 additions and 242 deletions

View File

@@ -866,6 +866,7 @@
<activity
android:name=".localepicker.AppLocalePickerActivity"
android:label="@string/app_locale_picker_title"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="true" >
<intent-filter>
<action android:name="android.settings.APP_LOCALE_SETTINGS" />
@@ -1451,7 +1452,8 @@
<activity
android:name=".datausage.AppDataUsageActivity"
android:exported="true"
android:noHistory="true">
android:noHistory="true"
android:permission="android.permission.QUERY_ALL_PACKAGES">
<intent-filter android:priority="1">
<action android:name="android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
@@ -1521,6 +1523,7 @@
<activity-alias android:name=".applications.InstalledAppDetails"
android:label="@string/application_info_label"
android:exported="true"
android:permission="android.permission.QUERY_ALL_PACKAGES"
android:targetActivity=".applications.InstalledAppDetailsTop">
<intent-filter android:priority="1">
<action android:name="android.settings.APPLICATION_DETAILS_SETTINGS" />
@@ -1534,7 +1537,8 @@
<activity android:name=".applications.InstalledAppOpenByDefaultActivity"
android:label="@string/application_info_label"
android:exported="true">
android:exported="true"
android:permission="android.permission.QUERY_ALL_PACKAGES">
<intent-filter android:priority="1">
<action android:name="android.settings.APP_OPEN_BY_DEFAULT_SETTINGS" />
<!-- Also catch legacy "com." prefixed action. -->
@@ -1905,7 +1909,8 @@
<activity
android:name="Settings$AppUsageAccessSettingsActivity"
android:exported="true"
android:label="@string/usage_access_title">
android:label="@string/usage_access_title"
android:permission="android.permission.QUERY_ALL_PACKAGES">
<intent-filter>
<action android:name="android.settings.USAGE_ACCESS_SETTINGS"/>
<category android:name="android.intent.category.DEFAULT"/>

View File

@@ -13,17 +13,19 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- TODO(b/208624929): Update to an UX approved icon. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:tint="?android:attr/colorControlNormal">
android:viewportHeight="24"
android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
<path
android:fillColor="#FFFFFFFF"
android:pathData="M18.5,1C16.01,1 14,3.01 14,5.5V8H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10c0,-1.1 -0.9,-2 -2,-2h-2V5.5C16,4.12 17.12,3 18.5,3C19.88,3 21,4.12 21,5.5V6h2V5.5C23,3.01 20.99,1 18.5,1zM18,10v10H6V10H18z"/>
android:fillColor="#000000"
android:pathData="M12,4.14l6,2.25v4.71c0,2.12-0.62,4-1.88,5.74c-1.13,1.55-2.48,2.56-4.12,3.09c-1.64-0.52-2.99-1.54-4.12-3.09 C6.62,15.1,6,13.22,6,11.1V6.39L12,4.14 M12,2L4,5v6.1c0,2.53,0.75,4.84,2.26,6.91C7.77,20.09,9.68,21.42,12,22 c2.32-0.58,4.23-1.91,5.74-3.99C19.25,15.94,20,13.63,20,11.1V5L12,2L12,2z" />
<path
android:fillColor="#000000"
android:pathData="M 10.95 15.55 L 7.42 12.02 L 8.85 10.6 L 10.95 12.7 L 15.17 8.47 L 16.6 9.9 Z" />
</vector>

View File

@@ -10195,18 +10195,18 @@
<string name="screen_pinning_description">
When an app is pinned, the pinned app may open other apps and personal data may be accessible.
\n\nTo use app pinning:
\t\n1.\tTurn on app pinning
\t\n2.\tOpen Overview
\t\n3.\tTap the app icon at the top of the screen, then tap Pin
\t\n1. Turn on app pinning
\t\n2. Open Overview
\t\n3. Tap the app icon at the top of the screen, then tap Pin
</string>
<!-- [CHAR LIMIT=none] Screen pinning description -->
<string name="screen_pinning_guest_user_description">
When an app is pinned, the pinned app may open other apps and personal data may be accessible.
\n\nIf you want to securely share your device with someone, try using a guest user instead.
\n\nTo use app pinning:
\t\n1.\tTurn on app pinning
\t\n2.\tOpen Overview
\t\n3.\tTap the app icon at the top of the screen, then tap Pin
\t\n1. Turn on app pinning
\t\n2. Open Overview
\t\n3. Tap the app icon at the top of the screen, then tap Pin
</string>
<!-- [CHAR LIMIT=300] Screen pinning title -->
<string name="screen_pinning_dialog_message">

View File

@@ -21,8 +21,7 @@
android:title="@string/data_usage_app_summary_title">
<com.android.settings.datausage.SpinnerPreference
android:key="cycle"
settings:isPreferenceVisible="false" />
android:key="cycle" />
<PreferenceCategory
android:key="app_data_usage_summary_category">
@@ -31,19 +30,22 @@
android:key="total_usage"
android:title="@string/total_size_label"
android:selectable="false"
android:layout="@layout/horizontal_preference" />
android:layout="@layout/horizontal_preference"
android:summary="@string/summary_placeholder" />
<Preference
android:key="foreground_usage"
android:title="@string/data_usage_label_foreground"
android:selectable="false"
android:layout="@layout/horizontal_preference" />
android:layout="@layout/horizontal_preference"
android:summary="@string/summary_placeholder" />
<Preference
android:key="background_usage"
android:title="@string/data_usage_label_background"
android:selectable="false"
android:layout="@layout/horizontal_preference" />
android:layout="@layout/horizontal_preference"
android:summary="@string/summary_placeholder" />
</PreferenceCategory>

View File

@@ -330,8 +330,8 @@ public class ManageApplications extends InstrumentedFragment
if (className.equals(Settings.NotificationReviewPermissionsActivity.class.getName())) {
// Special-case for a case where a user is directed to the all apps notification
// preferences page via a notification prompt to review permissions settings.
android.provider.Settings.Secure.putInt(getContext().getContentResolver(),
android.provider.Settings.Secure.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
android.provider.Settings.Global.putInt(getContext().getContentResolver(),
android.provider.Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
1); // USER_INTERACTED
}
} else if (className.equals(AppLocaleDetails.class.getName())) {

View File

@@ -144,8 +144,7 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE);
mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE);
mCycle = findPreference(KEY_CYCLE);
mCycleAdapter = new CycleAdapter(mContext, mCycle, mCycleListener);
initCycle();
final UidDetailProvider uidDetailProvider = getUidDetailProvider();
@@ -211,6 +210,8 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
removePreference(KEY_RESTRICT_BACKGROUND);
removePreference(KEY_APP_LIST);
}
addEntityHeader();
}
@Override
@@ -276,6 +277,17 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
return new UidDetailProvider(mContext);
}
private void initCycle() {
mCycle = findPreference(KEY_CYCLE);
mCycleAdapter = new CycleAdapter(mContext, mCycle, mCycleListener);
if (mCycles != null) {
// If coming from a page like DataUsageList where already has a selected cycle, display
// that before loading to reduce flicker.
mCycleAdapter.setInitialCycleList(mCycles, mSelectedCycle);
mCycle.setHasCycles(true);
}
}
private void updatePrefs(boolean restrictBackground, boolean unrestrictData) {
final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfMeteredDataRestricted(
mContext, mPackageName, UserHandle.getUserId(mAppItem.key));
@@ -308,9 +320,9 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
final long backgroundBytes, foregroundBytes;
if (mUsageData == null || position >= mUsageData.size()) {
backgroundBytes = foregroundBytes = 0;
mCycle.setVisible(false);
mCycle.setHasCycles(false);
} else {
mCycle.setVisible(true);
mCycle.setHasCycles(true);
final NetworkCycleDataForUid data = mUsageData.get(position);
backgroundBytes = data.getBackgroudUsage();
foregroundBytes = data.getForegroudUsage();
@@ -335,10 +347,8 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
return false;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@VisibleForTesting
void addEntityHeader() {
String pkg = mPackages.size() != 0 ? mPackages.valueAt(0) : null;
int uid = 0;
if (pkg != null) {

View File

@@ -13,24 +13,13 @@
*/
package com.android.settings.datausage;
import android.annotation.NonNull;
import android.app.usage.NetworkStats;
import android.content.Context;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.text.format.DateUtils;
import android.util.Pair;
import android.util.Range;
import android.widget.AdapterView;
import com.android.net.module.util.NetworkStatsUtils;
import com.android.settings.Utils;
import com.android.settingslib.net.ChartData;
import com.android.settingslib.net.NetworkCycleData;
import com.android.settingslib.widget.SettingsSpinnerAdapter;
import java.time.ZonedDateTime;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
@@ -45,7 +34,6 @@ public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem>
mSpinner = spinner;
mListener = listener;
mSpinner.setAdapter(this);
mSpinner.setOnItemSelectedListener(mListener);
}
/**
@@ -65,128 +53,14 @@ public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem>
return 0;
}
protected static long getTotalBytesForTimeRange(List<NetworkStats.Bucket> stats,
Range<Long> range) {
long bytes = 0L;
for (NetworkStats.Bucket bucket : stats) {
final Range<Long> bucketSpan = new Range<>(
bucket.getStartTimeStamp(), bucket.getEndTimeStamp());
// Only record bytes that overlapped with the given time range. For partially
// overlapped bucket, record rational bytes assuming the traffic is uniform
// distributed within the bucket.
try {
final Range<Long> overlapped = range.intersect(bucketSpan);
final long totalOfBucket = bucket.getRxBytes() + bucket.getTxBytes();
bytes += NetworkStatsUtils.multiplySafeByRational(totalOfBucket,
overlapped.getUpper() - overlapped.getLower(),
bucketSpan.getUpper() - bucketSpan.getLower());
} catch (IllegalArgumentException e) {
// Range disjoint, ignore.
continue;
}
}
return bytes;
}
@NonNull
private Range getTimeRangeOf(@NonNull List<NetworkStats.Bucket> stats) {
long start = Long.MAX_VALUE;
long end = Long.MIN_VALUE;
for (NetworkStats.Bucket bucket : stats) {
start = Math.min(start, bucket.getStartTimeStamp());
end = Math.max(end, bucket.getEndTimeStamp());
}
return new Range(start, end);
}
/**
* Rebuild list based on {@link NetworkPolicy} and available
* {@link List<NetworkStats.Bucket>} data. Always selects the newest item,
* updating the inspection range on chartData.
*/
@Deprecated
public boolean updateCycleList(NetworkPolicy policy, ChartData chartData) {
// stash away currently selected cycle to try restoring below
final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem)
mSpinner.getSelectedItem();
void setInitialCycleList(List<Long> cycles, long selectedCycle) {
clear();
final Context context = getContext();
long historyStart;
long historyEnd;
try {
final Range<Long> historyTimeRange = getTimeRangeOf(chartData.network);
historyStart = historyTimeRange.getLower();
historyEnd = historyTimeRange.getUpper();
} catch (IllegalArgumentException e) {
// Empty history.
final long now = System.currentTimeMillis();
historyStart = now;
historyEnd = now + 1;
}
boolean hasCycles = false;
if (policy != null) {
final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = NetworkPolicyManager
.cycleIterator(policy);
while (it.hasNext()) {
final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next();
final long cycleStart = cycle.first.toInstant().toEpochMilli();
final long cycleEnd = cycle.second.toInstant().toEpochMilli();
final boolean includeCycle;
if (chartData != null) {
final long bytesInCycle = getTotalBytesForTimeRange(chartData.network,
new Range<>(cycleStart, cycleEnd));
includeCycle = bytesInCycle > 0;
} else {
includeCycle = true;
}
if (includeCycle) {
add(new CycleAdapter.CycleItem(context, cycleStart, cycleEnd));
hasCycles = true;
}
for (int i = 0; i < cycles.size() - 1; i++) {
add(new CycleAdapter.CycleItem(getContext(), cycles.get(i + 1), cycles.get(i)));
if (cycles.get(i) == selectedCycle) {
mSpinner.setSelection(i);
}
}
if (!hasCycles) {
// no policy defined cycles; show entry for each four-week period
long cycleEnd = historyEnd;
while (cycleEnd > historyStart) {
final long cycleStart = cycleEnd - (DateUtils.WEEK_IN_MILLIS * 4);
final boolean includeCycle;
if (chartData != null) {
final long bytesInCycle = getTotalBytesForTimeRange(chartData.network,
new Range<>(cycleStart, cycleEnd));
includeCycle = bytesInCycle > 0;
} else {
includeCycle = true;
}
if (includeCycle) {
add(new CycleAdapter.CycleItem(context, cycleStart, cycleEnd));
}
cycleEnd = cycleStart;
}
}
// force pick the current cycle (first item)
if (getCount() > 0) {
final int position = findNearestPosition(previousItem);
mSpinner.setSelection(position);
// only force-update cycle when changed; skipping preserves any
// user-defined inspection region.
final CycleAdapter.CycleItem selectedItem = getItem(position);
if (!Objects.equals(selectedItem, previousItem)) {
mListener.onItemSelected(null, null, position, 0);
return false;
}
}
return true;
}
/**
@@ -194,6 +68,7 @@ public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem>
* updating the inspection range on chartData.
*/
public boolean updateCycleList(List<? extends NetworkCycleData> cycleData) {
mSpinner.setOnItemSelectedListener(mListener);
// stash away currently selected cycle to try restoring below
final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem)
mSpinner.getSelectedItem();
@@ -228,10 +103,6 @@ public class CycleAdapter extends SettingsSpinnerAdapter<CycleAdapter.CycleItem>
public long start;
public long end;
public CycleItem(CharSequence label) {
this.label = label;
}
public CycleItem(Context context, long start, long end) {
this.label = Utils.formatDateRange(context, start, end);
this.start = start;

View File

@@ -48,6 +48,7 @@ import android.widget.ImageView;
import android.widget.Spinner;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.loader.app.LoaderManager.LoaderCallbacks;
import androidx.loader.content.Loader;
import androidx.preference.Preference;
@@ -500,6 +501,17 @@ public class DataUsageList extends DataUsageBaseFragment
+ cycle.end + "]");
}
// Avoid from updating UI after #onStop.
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
return;
}
// Avoid from updating UI when async query still on-going.
// This could happen when a request from #onMobileDataEnabledChange.
if (mCycleData == null) {
return;
}
// update chart to show selected cycle, and update detail data
// to match updated sweep bounds.
mChart.setNetworkCycleData(mCycleData.get(position));

View File

@@ -31,6 +31,8 @@ public class SpinnerPreference extends Preference implements CycleAdapter.Spinne
private AdapterView.OnItemSelectedListener mListener;
private Object mCurrentObject;
private int mPosition;
private View mItemView;
private boolean mItemViewVisible = false;
public SpinnerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -63,12 +65,24 @@ public class SpinnerPreference extends Preference implements CycleAdapter.Spinne
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mItemView = holder.itemView;
mItemView.setVisibility(mItemViewVisible ? View.VISIBLE : View.INVISIBLE);
Spinner spinner = (Spinner) holder.findViewById(R.id.cycles_spinner);
spinner.setAdapter(mAdapter);
spinner.setSelection(mPosition);
spinner.setOnItemSelectedListener(mOnSelectedListener);
}
void setHasCycles(boolean hasData) {
setVisible(hasData);
if (hasData) {
mItemViewVisible = true;
if (mItemView != null) {
mItemView.setVisibility(View.VISIBLE);
}
}
}
@Override
protected void performClick(View view) {
view.findViewById(R.id.cycles_spinner).performClick();

View File

@@ -424,6 +424,9 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
@VisibleForTesting
void setUsageSummary(Preference preference, BatteryEntry entry) {
if (entry.getUid() == Process.SYSTEM_UID) {
return;
}
// Only show summary when usage time is longer than one minute
final long usageTimeMs = entry.getTimeInForegroundMs();
if (shouldShowSummary(entry) && usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) {

View File

@@ -30,7 +30,6 @@ import android.view.View;
import android.widget.FrameLayout;
import android.widget.ListView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.LocalePickerWithRegion;
import com.android.internal.app.LocaleStore;
import com.android.settings.R;
@@ -38,10 +37,6 @@ import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.appinfo.AppLocaleDetails;
import com.android.settings.core.SettingsBaseActivity;
/**
* TODO(b/223503670): Add unit test for AppLocalePickerActivity.
* A activity to show the locale picker and information page.
*/
public class AppLocalePickerActivity extends SettingsBaseActivity
implements LocalePickerWithRegion.LocaleSelectedListener {
private static final String TAG = AppLocalePickerActivity.class.getSimpleName();
@@ -128,8 +123,7 @@ public class AppLocalePickerActivity extends SettingsBaseActivity
return appLocaleDetailsContainer;
}
@VisibleForTesting
void launchLocalePickerPage() {
private void launchLocalePickerPage() {
// LocalePickerWithRegion use android.app.ListFragment. Thus, it can not use
// getSupportFragmentManager() to add this into container.
android.app.FragmentManager fragmentManager = getFragmentManager();

View File

@@ -37,6 +37,7 @@ import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.Settings.MobileNetworkActivity;
import com.android.settings.SettingsActivity;
import com.android.settings.datausage.BillingCyclePreferenceController;
import com.android.settings.datausage.DataUsageSummaryPreferenceController;
import com.android.settings.network.ActiveSubscriptionsListener;
@@ -54,6 +55,7 @@ import com.android.settingslib.utils.ThreadUtils;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
@@ -275,17 +277,37 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
Log.d(LOG_TAG, "Callback during onResume()");
return;
}
final SubscriptionInfo subInfo = SubscriptionUtil
.getSubscriptionOrDefault(getContext(), mSubId);
if (subInfo != null) {
/**
* Update the title when SIM stats got changed
*/
final Consumer<Activity> renameTitle = activity -> {
if (activity != null && !activity.isFinishing()) {
if (activity instanceof SettingsActivity) {
final CharSequence displayName = SubscriptionUtil
.getUniqueSubscriptionDisplayName(subInfo, activity);
((SettingsActivity)activity).setTitle(displayName);
}
}
};
ThreadUtils.postOnMainThread(() -> renameTitle.accept(getActivity()));
}
mActiveSubscriptionsListenerCount++;
if (mActiveSubscriptionsListenerCount != 1) {
return;
}
if (SubscriptionUtil.getSubscriptionOrDefault(getContext(), mSubId) == null) {
finishFragment();
return;
}
ThreadUtils.postOnMainThread(() -> {
if (subInfo == null) {
finishFragment();
return;
}
mActiveSubscriptionsListenerCount = 0;
redrawPreferenceControllers();
});

View File

@@ -35,6 +35,7 @@ import com.android.settings.media.MediaOutputIndicatorWorker;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settingslib.media.MediaDevice;
import com.android.settingslib.media.MediaOutputConstants;
public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceController {
private static final String TAG = "MediaVolumePreCtrl";
@@ -106,8 +107,10 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
final Intent intent = new Intent();
if (getWorker().isDeviceBroadcasting()) {
// TODO(b/229577323) : Get the intent action for the Media Output Broadcast Dialog
// in SystemUI
intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME);
intent.setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME,
getWorker().getActiveLocalMediaController().getPackageName());
} else {
// TODO(b/229577518) : Get the intent action of the Bluetooth Broadcast Dialog
// for user to choose the action

View File

@@ -15,18 +15,17 @@
*/
package com.android.settings.wifi.p2p;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
import android.net.wifi.WifiManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -70,6 +69,9 @@ public class WifiP2pPreferenceController extends AbstractPreferenceController
super.displayPreference(screen);
mWifiDirectPref = screen.findPreference(KEY_WIFI_DIRECT);
togglePreferences();
if (!mIsWifiDirectAllow) {
mWifiDirectPref.setSummary(R.string.not_allowed_by_ent);
}
}
@Override

View File

@@ -46,12 +46,9 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
private static final String WIFI_TETHER_SETTINGS = "wifi_tether";
private final TetheringManager mTetheringManager;
private final String[] mWifiRegexs;
private final WifiManager mWifiManager;
private final Lifecycle mLifecycle;
@VisibleForTesting
boolean mIsWifiTetheringAllow;
private boolean mIsWifiTetherable;
private WifiManager mWifiManager;
private boolean mIsWifiTetheringAllow;
private int mSoftApState;
@VisibleForTesting
Preference mPreference;
@@ -59,18 +56,32 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
WifiTetherSoftApManager mWifiTetherSoftApManager;
public WifiTetherPreferenceController(Context context, Lifecycle lifecycle) {
this(context, lifecycle, true /* initSoftApManager */);
this(context, lifecycle,
context.getSystemService(WifiManager.class),
context.getSystemService(TetheringManager.class),
true /* initSoftApManager */,
WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(context));
}
@VisibleForTesting
WifiTetherPreferenceController(Context context, Lifecycle lifecycle,
boolean initSoftApManager) {
WifiTetherPreferenceController(
Context context,
Lifecycle lifecycle,
WifiManager wifiManager,
TetheringManager tetheringManager,
boolean initSoftApManager,
boolean isWifiTetheringAllow) {
super(context);
mTetheringManager = context.getSystemService(TetheringManager.class);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mWifiRegexs = mTetheringManager.getTetherableWifiRegexs();
mIsWifiTetheringAllow = WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(context);
mLifecycle = lifecycle;
final String[] wifiRegexs = tetheringManager.getTetherableWifiRegexs();
if (wifiRegexs != null && wifiRegexs.length != 0) {
mIsWifiTetherable = true;
}
mIsWifiTetheringAllow = isWifiTetheringAllow;
if (!isWifiTetheringAllow) return;
mWifiManager = wifiManager;
if (lifecycle != null) {
lifecycle.addObserver(this);
}
@@ -81,9 +92,7 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
@Override
public boolean isAvailable() {
return mWifiRegexs != null
&& mWifiRegexs.length != 0
&& !Utils.isMonkeyRunning();
return mIsWifiTetherable && !Utils.isMonkeyRunning();
}
@Override
@@ -94,7 +103,10 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
// unavailable
return;
}
mPreference.setEnabled(mIsWifiTetheringAllow);
if (!mIsWifiTetheringAllow && mPreference.isEnabled()) {
mPreference.setEnabled(false);
mPreference.setSummary(R.string.not_allowed_by_ent);
}
}
@Override

View File

@@ -43,7 +43,6 @@ import android.os.Process;
import android.telephony.SubscriptionManager;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.view.View;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
@@ -96,6 +95,10 @@ public class AppDataUsageTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowEntityHeaderController.setUseMock(mHeaderController);
when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
when(mHeaderController.setUid(anyInt())).thenReturn(mHeaderController);
}
@After
@@ -163,10 +166,6 @@ public class AppDataUsageTest {
@Test
public void bindAppHeader_allWorkApps_shouldNotShowAppInfoLink() {
ShadowEntityHeaderController.setUseMock(mHeaderController);
when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
when(mHeaderController.setUid(anyInt())).thenReturn(mHeaderController);
mFragment = spy(new AppDataUsage());
when(mFragment.getPreferenceManager())
@@ -174,7 +173,7 @@ public class AppDataUsageTest {
doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
ReflectionHelpers.setField(mFragment, "mAppItem", mock(AppItem.class));
mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
mFragment.addEntityHeader();
verify(mHeaderController).setHasAppInfoLink(false);
}
@@ -196,16 +195,13 @@ public class AppDataUsageTest {
when(mPackageManager.getPackageUidAsUser(anyString(), anyInt()))
.thenReturn(fakeUserId);
ShadowEntityHeaderController.setUseMock(mHeaderController);
when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
when(mHeaderController.setUid(fakeUserId)).thenReturn(mHeaderController);
when(mHeaderController.setHasAppInfoLink(anyBoolean())).thenReturn(mHeaderController);
when(mFragment.getPreferenceManager())
.thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
mFragment.addEntityHeader();
verify(mHeaderController).setHasAppInfoLink(true);
verify(mHeaderController).setUid(fakeUserId);
@@ -268,7 +264,7 @@ public class AppDataUsageTest {
mFragment.bindData(0 /* position */);
verify(cycle).setVisible(false);
verify(cycle).setHasCycles(false);
}
@Test
@@ -293,7 +289,7 @@ public class AppDataUsageTest {
mFragment.bindData(0 /* position */);
verify(cycle).setVisible(true);
verify(cycle).setHasCycles(true);
verify(totalPref).setSummary(
DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2022 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.localepicker;
import static com.google.common.truth.Truth.assertThat;
import android.app.Activity;
import android.app.ApplicationPackageManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.InstallSourceInfo;
import android.net.Uri;
import android.os.Process;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
import androidx.fragment.app.Fragment;
import com.android.settings.R;
import com.android.settings.applications.AppInfoBase;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowTelephonyManager;
@RunWith(RobolectricTestRunner.class)
@Config(
shadows = {
AppLocalePickerActivityTest.ShadowApplicationPackageManager.class,
})
public class AppLocalePickerActivityTest {
private static final String TEST_PACKAGE_NAME = "com.android.settings";
private static final Uri TEST_PACKAGE_URI = Uri.parse("package:" + TEST_PACKAGE_NAME);
@Rule
public MockitoRule rule = MockitoJUnit.rule();
@Test
public void launchAppLocalePickerActivity_hasPackageName_success() {
ActivityController<TestAppLocalePickerActivity> controller =
initActivityController(true);
controller.create();
assertThat(controller.get().isFinishing()).isFalse();
}
@Test
public void launchAppLocalePickerActivity_intentWithoutPackageName_failed() {
ActivityController<TestAppLocalePickerActivity> controller =
initActivityController(false);
controller.create();
assertThat(controller.get().isFinishing()).isTrue();
}
private ActivityController<TestAppLocalePickerActivity> initActivityController(
boolean hasPackageName) {
Intent data = new Intent();
if (hasPackageName) {
data.setData(TEST_PACKAGE_URI);
}
data.putExtra(AppInfoBase.ARG_PACKAGE_UID, UserHandle.getUserId(Process.myUid()));
ActivityController<TestAppLocalePickerActivity> activityController =
Robolectric.buildActivity(TestAppLocalePickerActivity.class, data);
Activity activity = activityController.get();
ShadowTelephonyManager shadowTelephonyManager = Shadows.shadowOf(
activity.getSystemService(TelephonyManager.class));
shadowTelephonyManager.setSimCountryIso("US");
shadowTelephonyManager.setNetworkCountryIso("US");
return activityController;
}
private static class TestAppLocalePickerActivity extends AppLocalePickerActivity {
@Override
public Context createContextAsUser(UserHandle user, int flags) {
// return the current context as a work profile
return this;
}
}
@Implements(ApplicationPackageManager.class)
public static class ShadowApplicationPackageManager extends
org.robolectric.shadows.ShadowApplicationPackageManager {
@Implementation
protected Object getInstallSourceInfo(String packageName) {
return new InstallSourceInfo("", null, null, "");
}
}
}

View File

@@ -22,12 +22,10 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +38,7 @@ import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -142,6 +141,7 @@ public class WifiP2PPreferenceControllerTest {
mController.displayPreference(mScreen);
verify(mWifiDirectPreference).setEnabled(false);
verify(mWifiDirectPreference).setSummary(R.string.not_allowed_by_ent);
}
@Test

View File

@@ -19,30 +19,29 @@ package com.android.settings.wifi.tether;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.TetheringManager;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.UserManager;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@@ -56,53 +55,44 @@ public class WifiTetherPreferenceControllerTest {
private static final String SSID = "Pixel";
private Context mContext;
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Spy
Context mContext = ApplicationProvider.getApplicationContext();
@Mock
private Lifecycle mLifecycle;
@Mock
private TetheringManager mTetheringManager;
@Mock
private WifiManager mWifiManager;
@Mock
private UserManager mUserManager;
@Mock
private Bundle mBundle;
@Mock
private PreferenceScreen mScreen;
private SoftApConfiguration mSoftApConfiguration;
private WifiTetherPreferenceController mController;
private Lifecycle mLifecycle;
private LifecycleOwner mLifecycleOwner;
private PrimarySwitchPreference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
FakeFeatureFactory.setupForTest();
mPreference = new PrimarySwitchPreference(RuntimeEnvironment.application);
mPreference = new PrimarySwitchPreference(mContext);
when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
when(mUserManager.getUserRestrictions()).thenReturn(mBundle);
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
mSoftApConfiguration = new SoftApConfiguration.Builder().setSsid(SSID).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(mSoftApConfiguration);
when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"});
mController = new WifiTetherPreferenceController(mContext, mLifecycle,
false /* initSoftApManager */);
mController.mIsWifiTetheringAllow = true;
mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
mTetheringManager, false /* initSoftApManager */, true /* isWifiTetheringAllow */);
mController.displayPreference(mScreen);
}
@Test
public void isAvailable_noTetherRegex_shouldReturnFalse() {
when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(new String[]{});
mController = new WifiTetherPreferenceController(mContext, mLifecycle,
false /* initSoftApManager */);
mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
mTetheringManager, false /* initSoftApManager */, true /* isWifiTetheringAllow */);
assertThat(mController.isAvailable()).isFalse();
}
@@ -114,16 +104,19 @@ public class WifiTetherPreferenceControllerTest {
@Test
public void displayPreference_wifiTetheringNotAllowed_shouldDisable() {
mController.mIsWifiTetheringAllow = false;
mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
mTetheringManager, false /* initSoftApManager */, false /* isWifiTetheringAllow */);
mController.displayPreference(mScreen);
assertThat(mPreference.isEnabled()).isFalse();
assertThat(mPreference.getSummary()).isEqualTo("Not allowed by your organization");
}
@Test
public void displayPreference_wifiTetheringAllowed_shouldEnable() {
mController.mIsWifiTetheringAllow = true;
mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
mTetheringManager, false /* initSoftApManager */, true /* isWifiTetheringAllow */);
mController.displayPreference(mScreen);