Snap for 6593884 from 8e50511679 to mainline-release
Change-Id: Icc03fa21a8d7506ddd3181805eefe2bf8b2387ba
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
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.
|
||||
@@ -21,6 +21,7 @@
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:focusable="false"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<RelativeLayout
|
||||
@@ -30,13 +31,14 @@
|
||||
android:gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:focusable="false"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem" />
|
||||
|
||||
@@ -48,6 +50,7 @@
|
||||
android:layout_alignStart="@android:id/title"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:focusable="false"
|
||||
android:maxLines="2" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -59,6 +62,7 @@
|
||||
android:layout_marginStart="8dip"
|
||||
android:layout_marginEnd="8dip"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:focusable="true"
|
||||
android:clickable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- Cell Broadcast settings title. [CHAR LIMIT=50] -->
|
||||
<!-- Cell Broadcast settings title. [CHAR LIMIT=50]
|
||||
This settings will be shown on devices with Italian SIMs.
|
||||
Required Italian (it) translation for this message: "Allarmi Pubblici" -->
|
||||
<string name="cell_broadcast_settings">Public warnings</string>
|
||||
</resources>
|
||||
@@ -2752,6 +2752,10 @@
|
||||
<string name="peak_refresh_rate_title">Smooth Display</string>
|
||||
<!-- Display settings screen, peak refresh rate settings summary [CHAR LIMIT=NONE] -->
|
||||
<string name="peak_refresh_rate_summary">Automatically raises the refresh rate from 60 to 90 Hz for some content. Increases battery usage.</string>
|
||||
<!-- Display developer settings: Force to the highest refresh rate [CHAR LIMIT=NONE] -->
|
||||
<string name="force_high_refresh_rate_toggle">Smooth Display</string>
|
||||
<!-- Display developer settings: Force to the highest refresh rate description [CHAR LIMIT=NONE]-->
|
||||
<string name="force_high_refresh_rate_desc">Highest refresh rate for improved touch responsiveness & animation quality. Increases battery usage.</string>
|
||||
<!-- Display settings screen, setting option name to enable adaptive sleep [CHAR LIMIT=30] -->
|
||||
<string name="adaptive_sleep_title">Screen attention</string>
|
||||
<!-- Setting option summary when adaptive sleep is on [CHAR LIMIT=NONE] -->
|
||||
@@ -7280,7 +7284,7 @@
|
||||
<!-- Call Manager settings summary. [CHAR LIMIT=50] -->
|
||||
<string name="call_manager_summary"><xliff:g id="app">%1$s</xliff:g></string>
|
||||
<!-- Cell Broadcast settings title. [CHAR LIMIT=50] -->
|
||||
<string name="cell_broadcast_settings">Emergency alerts</string>
|
||||
<string name="cell_broadcast_settings">Wireless emergency alerts</string>
|
||||
<!-- Network operators settings title. [CHAR LIMIT=50] -->
|
||||
<string name="network_operators_settings">Network operators</string>
|
||||
<!-- Access point names title. [CHAR LIMIT=50] -->
|
||||
|
||||
@@ -256,6 +256,11 @@
|
||||
android:title="@string/overlay_settings_title"
|
||||
android:summary="@string/overlay_settings_summary" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="pref_key_peak_refresh_rate"
|
||||
android:title="@string/force_high_refresh_rate_toggle"
|
||||
android:summary="@string/force_high_refresh_rate_desc" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
||||
@@ -459,6 +459,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
controllers.add(new SelectDebugAppPreferenceController(context, fragment));
|
||||
controllers.add(new WaitForDebuggerPreferenceController(context));
|
||||
controllers.add(new EnableGpuDebugLayersPreferenceController(context));
|
||||
controllers.add(new ForcePeakRefreshRatePreferenceController(context));
|
||||
controllers.add(new EnableVerboseVendorLoggingPreferenceController(context));
|
||||
controllers.add(new VerifyAppsOverUsbPreferenceController(context));
|
||||
controllers.add(new ArtVerifierPreferenceController(context));
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.development;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
|
||||
|
||||
public class ForcePeakRefreshRatePreferenceController extends DeveloperOptionsPreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
|
||||
|
||||
@VisibleForTesting
|
||||
static float DEFAULT_REFRESH_RATE = 60f;
|
||||
|
||||
@VisibleForTesting
|
||||
static float NO_CONFIG = 0f;
|
||||
|
||||
@VisibleForTesting
|
||||
float mPeakRefreshRate;
|
||||
|
||||
private static final String TAG = "ForcePeakRefreshRateCtr";
|
||||
private static final String PREFERENCE_KEY = "pref_key_peak_refresh_rate";
|
||||
|
||||
public ForcePeakRefreshRatePreferenceController(Context context) {
|
||||
super(context);
|
||||
|
||||
final DisplayManager dm = context.getSystemService(DisplayManager.class);
|
||||
final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
|
||||
|
||||
if (display == null) {
|
||||
Log.w(TAG, "No valid default display device");
|
||||
mPeakRefreshRate = DEFAULT_REFRESH_RATE;
|
||||
} else {
|
||||
mPeakRefreshRate = findPeakRefreshRate(display.getSupportedModes());
|
||||
}
|
||||
|
||||
Log.d(TAG, "DEFAULT_REFRESH_RATE : " + DEFAULT_REFRESH_RATE
|
||||
+ " mPeakRefreshRate : " + mPeakRefreshRate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return PREFERENCE_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final boolean isEnabled = (Boolean) newValue;
|
||||
forcePeakRefreshRate(isEnabled);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
((SwitchPreference) mPreference).setChecked(isForcePeakRefreshRateEnabled());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (mContext.getResources().getBoolean(R.bool.config_show_smooth_display)) {
|
||||
return mPeakRefreshRate > DEFAULT_REFRESH_RATE;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchDisabled() {
|
||||
super.onDeveloperOptionsSwitchDisabled();
|
||||
Settings.System.putFloat(mContext.getContentResolver(),
|
||||
Settings.System.MIN_REFRESH_RATE, NO_CONFIG);
|
||||
|
||||
((SwitchPreference) mPreference).setChecked(false);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void forcePeakRefreshRate(boolean enable) {
|
||||
final float peakRefreshRate = enable ? mPeakRefreshRate : NO_CONFIG;
|
||||
Settings.System.putFloat(mContext.getContentResolver(),
|
||||
Settings.System.MIN_REFRESH_RATE, peakRefreshRate);
|
||||
}
|
||||
|
||||
boolean isForcePeakRefreshRateEnabled() {
|
||||
final float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
|
||||
Settings.System.MIN_REFRESH_RATE, NO_CONFIG);
|
||||
|
||||
return peakRefreshRate >= mPeakRefreshRate;
|
||||
}
|
||||
|
||||
private float findPeakRefreshRate(Display.Mode[] modes) {
|
||||
float peakRefreshRate = DEFAULT_REFRESH_RATE;
|
||||
for (Display.Mode mode : modes) {
|
||||
if (Math.round(mode.getRefreshRate()) > DEFAULT_REFRESH_RATE) {
|
||||
peakRefreshRate = mode.getRefreshRate();
|
||||
}
|
||||
}
|
||||
|
||||
return peakRefreshRate;
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
@@ -34,19 +35,32 @@ import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
public class ApnPreference extends Preference implements CompoundButton.OnCheckedChangeListener {
|
||||
/**
|
||||
* Preference of APN UI entry
|
||||
*/
|
||||
public class ApnPreference extends Preference implements CompoundButton.OnCheckedChangeListener,
|
||||
View.OnClickListener {
|
||||
final static String TAG = "ApnPreference";
|
||||
|
||||
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
/**
|
||||
* Constructor of Preference
|
||||
*/
|
||||
public ApnPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor of Preference
|
||||
*/
|
||||
public ApnPreference(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.apnPreferenceStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor of Preference
|
||||
*/
|
||||
public ApnPreference(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -61,6 +75,9 @@ public class ApnPreference extends Preference implements CompoundButton.OnChecke
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
super.onBindViewHolder(view);
|
||||
|
||||
final RelativeLayout textArea = (RelativeLayout) view.findViewById(R.id.text_layout);
|
||||
textArea.setOnClickListener(this);
|
||||
|
||||
final View widget = view.findViewById(R.id.apn_radiobutton);
|
||||
if ((widget != null) && widget instanceof RadioButton) {
|
||||
final RadioButton rb = (RadioButton) widget;
|
||||
@@ -111,22 +128,25 @@ public class ApnPreference extends Preference implements CompoundButton.OnChecke
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
public void onClick(View layoutView) {
|
||||
super.onClick();
|
||||
final Context context = getContext();
|
||||
if (context != null) {
|
||||
if (mHideDetails) {
|
||||
Toast.makeText(context, context.getString(
|
||||
R.string.cannot_change_apn_toast), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
final int pos = Integer.parseInt(getKey());
|
||||
final Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
|
||||
final Intent editIntent = new Intent(Intent.ACTION_EDIT, url);
|
||||
editIntent.putExtra(ApnSettings.SUB_ID, mSubId);
|
||||
editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
context.startActivity(editIntent);
|
||||
final int pos = Integer.parseInt(getKey());
|
||||
if (context == null) {
|
||||
Log.w(TAG, "No context available for pos=" + pos);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mHideDetails) {
|
||||
Toast.makeText(context, context.getString(
|
||||
R.string.cannot_change_apn_toast), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
final Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
|
||||
final Intent editIntent = new Intent(Intent.ACTION_EDIT, url);
|
||||
editIntent.putExtra(ApnSettings.SUB_ID, mSubId);
|
||||
editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
context.startActivity(editIntent);
|
||||
}
|
||||
|
||||
public void setSelectable(boolean selectable) {
|
||||
|
||||
@@ -16,13 +16,19 @@
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
|
||||
import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
|
||||
import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
|
||||
import static android.net.TetheringManager.TETHERING_INVALID;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
|
||||
import static android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX;
|
||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.TetheringConstants;
|
||||
import android.net.TetheringManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.UserHandle;
|
||||
@@ -52,23 +58,19 @@ public class TetherProvisioningActivity extends Activity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mResultReceiver = (ResultReceiver)getIntent().getParcelableExtra(
|
||||
ConnectivityManager.EXTRA_PROVISION_CALLBACK);
|
||||
mResultReceiver = (ResultReceiver) getIntent().getParcelableExtra(EXTRA_PROVISION_CALLBACK);
|
||||
|
||||
final int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
|
||||
ConnectivityManager.TETHERING_INVALID);
|
||||
final int tetherType = getIntent().getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID);
|
||||
|
||||
final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID,
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
|
||||
final int subId = SubscriptionManager.getActiveDataSubscriptionId();
|
||||
if (tetherSubId != subId) {
|
||||
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
|
||||
mResultReceiver.send(TetheringManager.TETHER_ERROR_PROVISIONING_FAILED, null);
|
||||
mResultReceiver.send(TETHER_ERROR_PROVISIONING_FAILED, null);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
String[] provisionApp = getIntent().getStringArrayExtra(
|
||||
TetheringConstants.EXTRA_RUN_PROVISION);
|
||||
String[] provisionApp = getIntent().getStringArrayExtra(EXTRA_RUN_PROVISION);
|
||||
if (provisionApp == null || provisionApp.length < 2) {
|
||||
final Resources res = Utils.getResourcesForSubId(this, subId);
|
||||
provisionApp = res.getStringArray(
|
||||
@@ -77,8 +79,8 @@ public class TetherProvisioningActivity extends Activity {
|
||||
final Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.setClassName(provisionApp[0], provisionApp[1]);
|
||||
intent.putExtra(EXTRA_TETHER_TYPE, tetherType);
|
||||
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
|
||||
intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, mResultReceiver);
|
||||
intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
|
||||
intent.putExtra(EXTRA_PROVISION_CALLBACK, mResultReceiver);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]);
|
||||
}
|
||||
@@ -86,7 +88,7 @@ public class TetherProvisioningActivity extends Activity {
|
||||
if (getPackageManager().queryIntentActivities(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
|
||||
Log.e(TAG, "Provisioning app is configured, but not available.");
|
||||
mResultReceiver.send(TetheringManager.TETHER_ERROR_PROVISIONING_FAILED, null);
|
||||
mResultReceiver.send(TETHER_ERROR_PROVISIONING_FAILED, null);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
@@ -99,9 +101,8 @@ public class TetherProvisioningActivity extends Activity {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
if (requestCode == PROVISION_REQUEST) {
|
||||
if (DEBUG) Log.d(TAG, "Got result from app: " + resultCode);
|
||||
int result = resultCode == Activity.RESULT_OK ?
|
||||
TetheringManager.TETHER_ERROR_NO_ERROR :
|
||||
TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
|
||||
int result = resultCode == Activity.RESULT_OK
|
||||
? TETHER_ERROR_NO_ERROR : TETHER_ERROR_PROVISIONING_FAILED;
|
||||
mResultReceiver.send(result, null);
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.RoutingSessionInfo;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
@@ -136,11 +135,6 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final MediaDevice device = mLocalMediaManager.getMediaDeviceById(preference.getKey());
|
||||
if (device == null) {
|
||||
Log.e(TAG, "Unable to find " + preference.getKey() + " to set volume");
|
||||
return false;
|
||||
}
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
mLocalMediaManager.adjustSessionVolume(preference.getKey(), (int) newValue);
|
||||
});
|
||||
@@ -184,6 +178,5 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
|
||||
|
||||
@Override
|
||||
public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -821,6 +821,14 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mUserPassword != null) {
|
||||
mUserPassword.zeroize();
|
||||
}
|
||||
// Force a garbage collection immediately to remove remnant of user password shards
|
||||
// from memory.
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -530,6 +530,19 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mCurrentCredential != null) {
|
||||
mCurrentCredential.zeroize();
|
||||
}
|
||||
// Force a garbage collection immediately to remove remnant of user password shards
|
||||
// from memory.
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
protected int getStageType() {
|
||||
return mForFingerprint ? Stage.TYPE_FINGERPRINT :
|
||||
mForFace ? Stage.TYPE_FACE :
|
||||
|
||||
@@ -617,6 +617,19 @@ public class ChooseLockPattern extends SettingsActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mCurrentCredential != null) {
|
||||
mCurrentCredential.zeroize();
|
||||
}
|
||||
// Force a garbage collection immediately to remove remnant of user password shards
|
||||
// from memory.
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
protected Intent getRedactionInterstitialIntent(Context context) {
|
||||
return RedactionInterstitial.createStartIntent(context, mUserId);
|
||||
}
|
||||
|
||||
@@ -157,6 +157,16 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
// Force a garbage collection immediately to remove remnant of user password shards
|
||||
// from memory.
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
super.finish();
|
||||
|
||||
@@ -217,6 +217,17 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mPasswordEntry.setText(null);
|
||||
// Force a garbage collection immediately to remove remnant of user password shards
|
||||
// from memory.
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
private int getDefaultHeader() {
|
||||
if (mFrp) {
|
||||
return mIsAlpha ? R.string.lockpassword_confirm_your_password_header_frp
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
package com.android.settings.wifi.tether;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This receiver catches when quick settings turns off the hotspot, so we can
|
||||
* cancel the alarm in that case. All other cancels are handled in tethersettings.
|
||||
*/
|
||||
public class HotspotOffReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = "HotspotOffReceiver";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private Context mContext;
|
||||
private boolean mRegistered;
|
||||
|
||||
public HotspotOffReceiver(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) {
|
||||
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
if (wifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED) {
|
||||
if (DEBUG) Log.d(TAG, "TetherService.cancelRecheckAlarmIfNecessary called");
|
||||
// The hotspot has been turned off, we don't need to recheck tethering.
|
||||
TetherService.cancelRecheckAlarmIfNecessary(
|
||||
context, ConnectivityManager.TETHERING_WIFI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void register() {
|
||||
if (!mRegistered) {
|
||||
mContext.registerReceiver(this,
|
||||
new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION));
|
||||
mRegistered = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
if (mRegistered) {
|
||||
mContext.unregisterReceiver(this);
|
||||
mRegistered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,15 +16,24 @@
|
||||
|
||||
package com.android.settings.wifi.tether;
|
||||
|
||||
import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
|
||||
import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
|
||||
import static android.net.TetheringConstants.EXTRA_REM_TETHER_TYPE;
|
||||
import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
|
||||
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
|
||||
import static android.net.TetheringManager.TETHERING_ETHERNET;
|
||||
import static android.net.TetheringManager.TETHERING_INVALID;
|
||||
import static android.net.TetheringManager.TETHERING_USB;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||
import static android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX;
|
||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothPan;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.BluetoothProfile.ServiceListener;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -33,10 +42,9 @@ import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.TetheringManager;
|
||||
import android.os.IBinder;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.SystemClock;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
@@ -74,7 +82,6 @@ public class TetherService extends Service {
|
||||
private TetherServiceWrapper mWrapper;
|
||||
private ArrayList<Integer> mCurrentTethers;
|
||||
private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
|
||||
private HotspotOffReceiver mHotspotReceiver;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
@@ -93,18 +100,16 @@ public class TetherService extends Service {
|
||||
mCurrentTethers = stringToTethers(prefs.getString(KEY_TETHERS, ""));
|
||||
mCurrentTypeIndex = 0;
|
||||
mPendingCallbacks = new ArrayMap<>(3);
|
||||
mPendingCallbacks.put(ConnectivityManager.TETHERING_WIFI, new ArrayList<ResultReceiver>());
|
||||
mPendingCallbacks.put(ConnectivityManager.TETHERING_USB, new ArrayList<ResultReceiver>());
|
||||
mPendingCallbacks.put(
|
||||
ConnectivityManager.TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>());
|
||||
mHotspotReceiver = new HotspotOffReceiver(this);
|
||||
mPendingCallbacks.put(TETHERING_WIFI, new ArrayList<ResultReceiver>());
|
||||
mPendingCallbacks.put(TETHERING_USB, new ArrayList<ResultReceiver>());
|
||||
mPendingCallbacks.put(TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>());
|
||||
mPendingCallbacks.put(TETHERING_ETHERNET, new ArrayList<ResultReceiver>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (intent.hasExtra(EXTRA_SUBID)) {
|
||||
final int tetherSubId = intent.getIntExtra(EXTRA_SUBID,
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
final int tetherSubId = intent.getIntExtra(EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
|
||||
final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
|
||||
if (tetherSubId != subId) {
|
||||
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
|
||||
@@ -114,18 +119,16 @@ public class TetherService extends Service {
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
if (intent.hasExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE)) {
|
||||
int type = intent.getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
|
||||
ConnectivityManager.TETHERING_INVALID);
|
||||
ResultReceiver callback =
|
||||
intent.getParcelableExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK);
|
||||
if (intent.hasExtra(EXTRA_ADD_TETHER_TYPE)) {
|
||||
int type = intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID);
|
||||
ResultReceiver callback = intent.getParcelableExtra(EXTRA_PROVISION_CALLBACK);
|
||||
if (callback != null) {
|
||||
List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type);
|
||||
if (callbacksForType != null) {
|
||||
callbacksForType.add(callback);
|
||||
} else {
|
||||
// Invalid tether type. Just ignore this request and report failure.
|
||||
callback.send(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE, null);
|
||||
callback.send(TETHER_ERROR_UNKNOWN_IFACE, null);
|
||||
stopSelf();
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
@@ -137,30 +140,20 @@ public class TetherService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
if (intent.hasExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE)) {
|
||||
if (intent.hasExtra(EXTRA_REM_TETHER_TYPE)) {
|
||||
if (!mInProvisionCheck) {
|
||||
int type = intent.getIntExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE,
|
||||
ConnectivityManager.TETHERING_INVALID);
|
||||
int type = intent.getIntExtra(EXTRA_REM_TETHER_TYPE, TETHERING_INVALID);
|
||||
int index = mCurrentTethers.indexOf(type);
|
||||
if (DEBUG) Log.d(TAG, "Removing tether " + type + ", index " + index);
|
||||
if (index >= 0) {
|
||||
removeTypeAtIndex(index);
|
||||
}
|
||||
cancelAlarmIfNecessary();
|
||||
} else {
|
||||
if (DEBUG) Log.d(TAG, "Don't cancel alarm during provisioning");
|
||||
if (DEBUG) Log.d(TAG, "Don't remove tether type during provisioning");
|
||||
}
|
||||
}
|
||||
|
||||
// Only set the alarm if we have one tether, meaning the one just added,
|
||||
// to avoid setting it when it was already set previously for another
|
||||
// type.
|
||||
if (intent.getBooleanExtra(ConnectivityManager.EXTRA_SET_ALARM, false)
|
||||
&& mCurrentTethers.size() == 1) {
|
||||
scheduleAlarm();
|
||||
}
|
||||
|
||||
if (intent.getBooleanExtra(ConnectivityManager.EXTRA_RUN_PROVISION, false)) {
|
||||
if (intent.getBooleanExtra(EXTRA_RUN_PROVISION, false)) {
|
||||
startProvisioning(mCurrentTypeIndex);
|
||||
} else if (!mInProvisionCheck) {
|
||||
// If we aren't running any provisioning, no reason to stay alive.
|
||||
@@ -182,16 +175,11 @@ public class TetherService extends Service {
|
||||
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
|
||||
prefs.edit().putString(KEY_TETHERS, tethersToString(mCurrentTethers)).commit();
|
||||
|
||||
unregisterReceivers();
|
||||
unregisterReceiver(mReceiver);
|
||||
if (DEBUG) Log.d(TAG, "Destroying TetherService");
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void unregisterReceivers() {
|
||||
unregisterReceiver(mReceiver);
|
||||
mHotspotReceiver.unregister();
|
||||
}
|
||||
|
||||
private void removeTypeAtIndex(int index) {
|
||||
mCurrentTethers.remove(index);
|
||||
// If we are currently in the middle of a check, we may need to adjust the
|
||||
@@ -202,11 +190,6 @@ public class TetherService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setHotspotOffReceiver(HotspotOffReceiver receiver) {
|
||||
mHotspotReceiver = receiver;
|
||||
}
|
||||
|
||||
private ArrayList<Integer> stringToTethers(String tethersStr) {
|
||||
ArrayList<Integer> ret = new ArrayList<Integer>();
|
||||
if (TextUtils.isEmpty(tethersStr)) return ret;
|
||||
@@ -231,32 +214,9 @@ public class TetherService extends Service {
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private void disableWifiTethering() {
|
||||
ConnectivityManager cm =
|
||||
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
cm.stopTethering(ConnectivityManager.TETHERING_WIFI);
|
||||
}
|
||||
|
||||
private void disableUsbTethering() {
|
||||
ConnectivityManager cm =
|
||||
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
cm.setUsbTethering(false);
|
||||
}
|
||||
|
||||
private void disableBtTethering() {
|
||||
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (adapter != null) {
|
||||
adapter.getProfileProxy(this, new ServiceListener() {
|
||||
@Override
|
||||
public void onServiceDisconnected(int profile) { }
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
||||
((BluetoothPan) proxy).setBluetoothTethering(false);
|
||||
adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
|
||||
}
|
||||
}, BluetoothProfile.PAN);
|
||||
}
|
||||
private void disableTethering(final int tetheringType) {
|
||||
final TetheringManager tm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
|
||||
tm.stopTethering(tetheringType);
|
||||
}
|
||||
|
||||
private void startProvisioning(int index) {
|
||||
@@ -279,7 +239,7 @@ public class TetherService extends Service {
|
||||
Intent intent = new Intent(provisionAction);
|
||||
int type = mCurrentTethers.get(index);
|
||||
intent.putExtra(TETHER_CHOICE, type);
|
||||
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
|
||||
intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
|
||||
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND
|
||||
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
|
||||
|
||||
@@ -304,55 +264,13 @@ public class TetherService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void scheduleAlarm() {
|
||||
Intent intent = new Intent(this, TetherService.class);
|
||||
intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
|
||||
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
||||
int period = getResourceForActiveDataSubId().getInteger(
|
||||
com.android.internal.R.integer.config_mobile_hotspot_provision_check_period);
|
||||
long periodMs = period * MS_PER_HOUR;
|
||||
long firstTime = SystemClock.elapsedRealtime() + periodMs;
|
||||
if (DEBUG) Log.d(TAG, "Scheduling alarm at interval " + periodMs);
|
||||
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, firstTime, periodMs,
|
||||
pendingIntent);
|
||||
mHotspotReceiver.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the recheck alarm only if no tethering is currently active.
|
||||
*
|
||||
* Runs in the background, to get access to bluetooth service that takes time to bind.
|
||||
*/
|
||||
public static void cancelRecheckAlarmIfNecessary(final Context context, int type) {
|
||||
Intent intent = new Intent(context, TetherService.class);
|
||||
intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void cancelAlarmIfNecessary() {
|
||||
if (mCurrentTethers.size() != 0) {
|
||||
if (DEBUG) Log.d(TAG, "Tethering still active, not cancelling alarm");
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent(this, TetherService.class);
|
||||
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
|
||||
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
||||
alarmManager.cancel(pendingIntent);
|
||||
if (DEBUG) Log.d(TAG, "Tethering no longer active, canceling recheck");
|
||||
mHotspotReceiver.unregister();
|
||||
}
|
||||
|
||||
private void fireCallbacksForType(int type, int result) {
|
||||
List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type);
|
||||
if (callbacksForType == null) {
|
||||
return;
|
||||
}
|
||||
int errorCode = result == RESULT_OK ? ConnectivityManager.TETHER_ERROR_NO_ERROR :
|
||||
ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
|
||||
int errorCode = result == RESULT_OK ? TETHER_ERROR_NO_ERROR :
|
||||
TETHER_ERROR_PROVISIONING_FAILED;
|
||||
for (ResultReceiver callback : callbacksForType) {
|
||||
if (DEBUG) Log.d(TAG, "Firing result: " + errorCode + " to callback");
|
||||
callback.send(errorCode, null);
|
||||
@@ -375,19 +293,7 @@ public class TetherService extends Service {
|
||||
int checkType = mCurrentTethers.get(mCurrentTypeIndex);
|
||||
mInProvisionCheck = false;
|
||||
int result = intent.getIntExtra(EXTRA_RESULT, RESULT_DEFAULT);
|
||||
if (result != RESULT_OK) {
|
||||
switch (checkType) {
|
||||
case ConnectivityManager.TETHERING_WIFI:
|
||||
disableWifiTethering();
|
||||
break;
|
||||
case ConnectivityManager.TETHERING_BLUETOOTH:
|
||||
disableBtTethering();
|
||||
break;
|
||||
case ConnectivityManager.TETHERING_USB:
|
||||
disableUsbTethering();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result != RESULT_OK) disableTethering(checkType);
|
||||
fireCallbacksForType(checkType, result);
|
||||
|
||||
if (++mCurrentTypeIndex >= mCurrentTethers.size()) {
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.development;
|
||||
|
||||
import static com.android.settings.development.ForcePeakRefreshRatePreferenceController.DEFAULT_REFRESH_RATE;
|
||||
import static com.android.settings.development.ForcePeakRefreshRatePreferenceController.NO_CONFIG;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ForcePeakRefreshRatePreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private SwitchPreference mPreference;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
private Context mContext;
|
||||
private ForcePeakRefreshRatePreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = new ForcePeakRefreshRatePreferenceController(mContext);
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
|
||||
when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
|
||||
mController.displayPreference(mScreen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_preferenceChecked_shouldEnableForcePeak() {
|
||||
mController.mPeakRefreshRate = 88f;
|
||||
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
|
||||
assertThat(Settings.System.getFloat(mContext.getContentResolver(),
|
||||
Settings.System.MIN_REFRESH_RATE, NO_CONFIG)).isEqualTo(88f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_preferenceUnchecked_shouldDisableForcePeak() {
|
||||
mController.mPeakRefreshRate = 88f;
|
||||
|
||||
mController.onPreferenceChange(mPreference, false);
|
||||
|
||||
assertThat(Settings.System.getFloat(mContext.getContentResolver(),
|
||||
Settings.System.MIN_REFRESH_RATE, NO_CONFIG)).isEqualTo(NO_CONFIG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_enableForcePeak_shouldCheckedToggle() {
|
||||
mController.mPeakRefreshRate = 88f;
|
||||
mController.forcePeakRefreshRate(true);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setChecked(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_disableForcePeak_shouldUncheckedToggle() {
|
||||
mController.mPeakRefreshRate = 88f;
|
||||
mController.forcePeakRefreshRate(false);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setChecked(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "mcc999")
|
||||
public void isAvailable_withConfigNoShow_returnUnsupported() {
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_refreshRateLargerThanDefault_returnTrue() {
|
||||
mController.mPeakRefreshRate = DEFAULT_REFRESH_RATE + 1;
|
||||
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_refreshRateEqualToDefault_returnFalse() {
|
||||
mController.mPeakRefreshRate = DEFAULT_REFRESH_RATE;
|
||||
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeveloperOptionsDisabled_shouldDisablePreference() {
|
||||
mController.onDeveloperOptionsSwitchDisabled();
|
||||
|
||||
assertThat(Settings.System.getFloat(mContext.getContentResolver(),
|
||||
Settings.System.MIN_REFRESH_RATE, -1f)).isEqualTo(NO_CONFIG);
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* 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.wifi.tether;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.shadows.ShadowApplication;
|
||||
import org.robolectric.shadows.ShadowApplication.Wrapper;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class TetherServiceTest {
|
||||
|
||||
private static final int CHECK_PERIOD_HOURS = 24;
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
|
||||
private Context mAppContext;
|
||||
private TetherService mService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mAppContext = RuntimeEnvironment.application;
|
||||
mService = spy(new TetherService());
|
||||
ReflectionHelpers.setField(mService, "mBase", mAppContext);
|
||||
mService.setHotspotOffReceiver(new HotspotOffReceiver(mContext));
|
||||
doReturn(CHECK_PERIOD_HOURS).when(mResources).getInteger(
|
||||
com.android.internal.R.integer.config_mobile_hotspot_provision_check_period);
|
||||
doReturn(mResources).when(mService).getResourceForActiveDataSubId();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scheduleAlarm_shouldRegisterReceiver() {
|
||||
mService.setHotspotOffReceiver(new HotspotOffReceiver(mAppContext));
|
||||
|
||||
mService.scheduleAlarm();
|
||||
|
||||
boolean found = false;
|
||||
for (Wrapper wrapper : ShadowApplication.getInstance().getRegisteredReceivers()) {
|
||||
if (wrapper.intentFilter.matchAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(found).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancelAlarmIfNecessary_hasActiveTethers_shouldNotUnregisterReceiver() {
|
||||
mService.scheduleAlarm();
|
||||
final ArrayList<Integer> tethers = new ArrayList<>();
|
||||
tethers.add(1);
|
||||
ReflectionHelpers.setField(mService, "mCurrentTethers", tethers);
|
||||
|
||||
mService.cancelAlarmIfNecessary();
|
||||
|
||||
verify(mContext, never()).unregisterReceiver(any(HotspotOffReceiver.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancelAlarmIfNecessary_noActiveTethers_shouldUnregisterReceiver() {
|
||||
final ArrayList<Integer> tethers = new ArrayList<>();
|
||||
ReflectionHelpers.setField(mService, "mCurrentTethers", tethers);
|
||||
mService.scheduleAlarm();
|
||||
|
||||
mService.cancelAlarmIfNecessary();
|
||||
|
||||
verify(mContext).unregisterReceiver(any(HotspotOffReceiver.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDestroy_shouldUnregisterReceiver() {
|
||||
final ArrayList<Integer> tethers = new ArrayList<>();
|
||||
ReflectionHelpers.setField(mService, "mCurrentTethers", tethers);
|
||||
ReflectionHelpers.setField(mService, "mBase", mContext);
|
||||
final SharedPreferences prefs = mock(SharedPreferences .class);
|
||||
final SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class);
|
||||
when(mContext.getSharedPreferences(anyString(), anyInt())).thenReturn(prefs);
|
||||
when(prefs.edit()).thenReturn(editor);
|
||||
when(editor.putString(anyString(), anyString())).thenReturn(editor);
|
||||
final HotspotOffReceiver hotspotOffReceiver = mock(HotspotOffReceiver.class);
|
||||
mService.setHotspotOffReceiver(hotspotOffReceiver);
|
||||
|
||||
mService.onDestroy();
|
||||
|
||||
verify(hotspotOffReceiver).unregister();
|
||||
}
|
||||
}
|
||||
@@ -16,27 +16,23 @@
|
||||
|
||||
package com.android.settings.wifi.tether;
|
||||
|
||||
import static android.net.ConnectivityManager.EXTRA_ADD_TETHER_TYPE;
|
||||
import static android.net.ConnectivityManager.EXTRA_PROVISION_CALLBACK;
|
||||
import static android.net.ConnectivityManager.EXTRA_REM_TETHER_TYPE;
|
||||
import static android.net.ConnectivityManager.EXTRA_RUN_PROVISION;
|
||||
import static android.net.ConnectivityManager.EXTRA_SET_ALARM;
|
||||
import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
|
||||
import static android.net.ConnectivityManager.TETHERING_INVALID;
|
||||
import static android.net.ConnectivityManager.TETHERING_USB;
|
||||
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
|
||||
import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
|
||||
import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
|
||||
import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
|
||||
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
|
||||
import static android.net.TetheringManager.TETHERING_INVALID;
|
||||
import static android.net.TetheringManager.TETHERING_USB;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
|
||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyLong;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -51,7 +47,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.TetheringManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.ResultReceiver;
|
||||
@@ -92,8 +88,7 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||
private ProvisionReceiver mProvisionReceiver;
|
||||
private Receiver mResultReceiver;
|
||||
|
||||
@Mock private AlarmManager mAlarmManager;
|
||||
@Mock private ConnectivityManager mConnectivityManager;
|
||||
@Mock private TetheringManager mTetheringManager;
|
||||
@Mock private PackageManager mPackageManager;
|
||||
@Mock private WifiManager mWifiManager;
|
||||
@Mock private SharedPreferences mPrefs;
|
||||
@@ -158,15 +153,6 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private void cancelAllProvisioning() {
|
||||
int[] types = new int[]{TETHERING_BLUETOOTH, TETHERING_WIFI, TETHERING_USB};
|
||||
for (int type : types) {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_REM_TETHER_TYPE, type);
|
||||
startService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartForProvision() {
|
||||
runProvisioningForType(TETHERING_WIFI);
|
||||
|
||||
@@ -184,19 +170,6 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||
assertTrue(mWrapper.isAppInactive(FAKE_PACKAGE_NAME));
|
||||
}
|
||||
|
||||
public void testScheduleRechecks() {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI);
|
||||
intent.putExtra(EXTRA_SET_ALARM, true);
|
||||
startService(intent);
|
||||
|
||||
long period = TEST_CHECK_PERIOD * MS_PER_HOUR;
|
||||
verify(mAlarmManager).setRepeating(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
|
||||
eq(period), mPiCaptor.capture());
|
||||
PendingIntent pi = mPiCaptor.getValue();
|
||||
assertEquals(TetherService.class.getName(), pi.getIntent().getComponent().getClassName());
|
||||
}
|
||||
|
||||
public void testStartMultiple() {
|
||||
runProvisioningForType(TETHERING_WIFI);
|
||||
|
||||
@@ -235,9 +208,9 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||
runProvisioningForType(TETHERING_WIFI);
|
||||
|
||||
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
|
||||
assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED));
|
||||
assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISIONING_FAILED));
|
||||
|
||||
verify(mConnectivityManager).stopTethering(ConnectivityManager.TETHERING_WIFI);
|
||||
verify(mTetheringManager).stopTethering(TETHERING_WIFI);
|
||||
}
|
||||
|
||||
public void testFailureStopsTethering_Usb() {
|
||||
@@ -246,24 +219,9 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||
runProvisioningForType(TETHERING_USB);
|
||||
|
||||
assertTrue(waitForProvisionRequest(TETHERING_USB));
|
||||
assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED));
|
||||
assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISIONING_FAILED));
|
||||
|
||||
verify(mConnectivityManager).setUsbTethering(eq(false));
|
||||
}
|
||||
|
||||
public void testCancelAlarm() {
|
||||
runProvisioningForType(TETHERING_WIFI);
|
||||
|
||||
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
|
||||
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_REM_TETHER_TYPE, TETHERING_WIFI);
|
||||
startService(intent);
|
||||
|
||||
verify(mAlarmManager).cancel(mPiCaptor.capture());
|
||||
PendingIntent pi = mPiCaptor.getValue();
|
||||
assertEquals(TetherService.class.getName(), pi.getIntent().getComponent().getClassName());
|
||||
verify(mTetheringManager).stopTethering(TETHERING_USB);
|
||||
}
|
||||
|
||||
public void testIgnoreOutdatedRequest() {
|
||||
@@ -387,10 +345,8 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
if (ALARM_SERVICE.equals(name)) {
|
||||
return mAlarmManager;
|
||||
} else if (CONNECTIVITY_SERVICE.equals(name)) {
|
||||
return mConnectivityManager;
|
||||
if (TETHERING_SERVICE.equals(name)) {
|
||||
return mTetheringManager;
|
||||
} else if (WIFI_SERVICE.equals(name)) {
|
||||
return mWifiManager;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user