Snap for 6593884 from 8e50511679 to mainline-release

Change-Id: Icc03fa21a8d7506ddd3181805eefe2bf8b2387ba
This commit is contained in:
android-build-team Robot
2020-06-16 07:09:33 +00:00
19 changed files with 448 additions and 421 deletions

View File

@@ -4,9 +4,9 @@
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,6 +21,7 @@
android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:minHeight="?android:attr/listPreferredItemHeight" android:minHeight="?android:attr/listPreferredItemHeight"
android:focusable="false"
android:gravity="center_vertical"> android:gravity="center_vertical">
<RelativeLayout <RelativeLayout
@@ -30,13 +31,14 @@
android:gravity="center_vertical" android:gravity="center_vertical"
android:layout_weight="1" android:layout_weight="1"
android:focusable="true" android:focusable="true"
android:clickable="true"
android:background="?android:attr/selectableItemBackground"> android:background="?android:attr/selectableItemBackground">
<TextView <TextView
android:id="@android:id/title" android:id="@android:id/title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="true" android:focusable="false"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem" /> android:textAppearance="?android:attr/textAppearanceListItem" />
@@ -48,6 +50,7 @@
android:layout_alignStart="@android:id/title" android:layout_alignStart="@android:id/title"
android:textAppearance="?android:attr/textAppearanceListItemSecondary" android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:focusable="false"
android:maxLines="2" /> android:maxLines="2" />
</RelativeLayout> </RelativeLayout>
@@ -59,6 +62,7 @@
android:layout_marginStart="8dip" android:layout_marginStart="8dip"
android:layout_marginEnd="8dip" android:layout_marginEnd="8dip"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:focusable="true"
android:clickable="true" /> android:clickable="true" />
</LinearLayout> </LinearLayout>

View File

@@ -14,6 +14,8 @@
limitations under the License. limitations under the License.
--> -->
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <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> <string name="cell_broadcast_settings">Public warnings</string>
</resources> </resources>

View File

@@ -2752,6 +2752,10 @@
<string name="peak_refresh_rate_title">Smooth Display</string> <string name="peak_refresh_rate_title">Smooth Display</string>
<!-- Display settings screen, peak refresh rate settings summary [CHAR LIMIT=NONE] --> <!-- 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> <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 &amp; animation quality. Increases battery usage.</string>
<!-- Display settings screen, setting option name to enable adaptive sleep [CHAR LIMIT=30] --> <!-- Display settings screen, setting option name to enable adaptive sleep [CHAR LIMIT=30] -->
<string name="adaptive_sleep_title">Screen attention</string> <string name="adaptive_sleep_title">Screen attention</string>
<!-- Setting option summary when adaptive sleep is on [CHAR LIMIT=NONE] --> <!-- Setting option summary when adaptive sleep is on [CHAR LIMIT=NONE] -->
@@ -7280,7 +7284,7 @@
<!-- Call Manager settings summary. [CHAR LIMIT=50] --> <!-- Call Manager settings summary. [CHAR LIMIT=50] -->
<string name="call_manager_summary"><xliff:g id="app">%1$s</xliff:g></string> <string name="call_manager_summary"><xliff:g id="app">%1$s</xliff:g></string>
<!-- Cell Broadcast settings title. [CHAR LIMIT=50] --> <!-- 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] --> <!-- Network operators settings title. [CHAR LIMIT=50] -->
<string name="network_operators_settings">Network operators</string> <string name="network_operators_settings">Network operators</string>
<!-- Access point names title. [CHAR LIMIT=50] --> <!-- Access point names title. [CHAR LIMIT=50] -->

View File

@@ -256,6 +256,11 @@
android:title="@string/overlay_settings_title" android:title="@string/overlay_settings_title"
android:summary="@string/overlay_settings_summary" /> 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>
<PreferenceCategory <PreferenceCategory

View File

@@ -459,6 +459,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controllers.add(new SelectDebugAppPreferenceController(context, fragment)); controllers.add(new SelectDebugAppPreferenceController(context, fragment));
controllers.add(new WaitForDebuggerPreferenceController(context)); controllers.add(new WaitForDebuggerPreferenceController(context));
controllers.add(new EnableGpuDebugLayersPreferenceController(context)); controllers.add(new EnableGpuDebugLayersPreferenceController(context));
controllers.add(new ForcePeakRefreshRatePreferenceController(context));
controllers.add(new EnableVerboseVendorLoggingPreferenceController(context)); controllers.add(new EnableVerboseVendorLoggingPreferenceController(context));
controllers.add(new VerifyAppsOverUsbPreferenceController(context)); controllers.add(new VerifyAppsOverUsbPreferenceController(context));
controllers.add(new ArtVerifierPreferenceController(context)); controllers.add(new ArtVerifierPreferenceController(context));

View File

@@ -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;
}
}

View File

@@ -27,6 +27,7 @@ import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.RadioButton; import android.widget.RadioButton;
import android.widget.RelativeLayout;
import android.widget.Toast; import android.widget.Toast;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -34,19 +35,32 @@ import androidx.preference.PreferenceViewHolder;
import com.android.settings.R; 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"; final static String TAG = "ApnPreference";
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
/**
* Constructor of Preference
*/
public ApnPreference(Context context, AttributeSet attrs, int defStyle) { public ApnPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
} }
/**
* Constructor of Preference
*/
public ApnPreference(Context context, AttributeSet attrs) { public ApnPreference(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.apnPreferenceStyle); this(context, attrs, R.attr.apnPreferenceStyle);
} }
/**
* Constructor of Preference
*/
public ApnPreference(Context context) { public ApnPreference(Context context) {
this(context, null); this(context, null);
} }
@@ -61,6 +75,9 @@ public class ApnPreference extends Preference implements CompoundButton.OnChecke
public void onBindViewHolder(PreferenceViewHolder view) { public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(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); final View widget = view.findViewById(R.id.apn_radiobutton);
if ((widget != null) && widget instanceof RadioButton) { if ((widget != null) && widget instanceof RadioButton) {
final RadioButton rb = (RadioButton) widget; final RadioButton rb = (RadioButton) widget;
@@ -111,22 +128,25 @@ public class ApnPreference extends Preference implements CompoundButton.OnChecke
} }
@Override @Override
protected void onClick() { public void onClick(View layoutView) {
super.onClick(); super.onClick();
final Context context = getContext(); final Context context = getContext();
if (context != null) { final int pos = Integer.parseInt(getKey());
if (mHideDetails) { if (context == null) {
Toast.makeText(context, context.getString( Log.w(TAG, "No context available for pos=" + pos);
R.string.cannot_change_apn_toast), Toast.LENGTH_LONG).show(); return;
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);
} }
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) { public void setSelectable(boolean selectable) {

View File

@@ -16,13 +16,19 @@
package com.android.settings.network; 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.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.TetheringConstants;
import android.net.TetheringManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.os.UserHandle; import android.os.UserHandle;
@@ -52,23 +58,19 @@ public class TetherProvisioningActivity extends Activity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mResultReceiver = (ResultReceiver)getIntent().getParcelableExtra( mResultReceiver = (ResultReceiver) getIntent().getParcelableExtra(EXTRA_PROVISION_CALLBACK);
ConnectivityManager.EXTRA_PROVISION_CALLBACK);
final int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, final int tetherType = getIntent().getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID);
ConnectivityManager.TETHERING_INVALID);
final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID, final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
final int subId = SubscriptionManager.getActiveDataSubscriptionId(); final int subId = SubscriptionManager.getActiveDataSubscriptionId();
if (tetherSubId != subId) { if (tetherSubId != subId) {
Log.e(TAG, "This Provisioning request is outdated, current subId: " + 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(); finish();
return; return;
} }
String[] provisionApp = getIntent().getStringArrayExtra( String[] provisionApp = getIntent().getStringArrayExtra(EXTRA_RUN_PROVISION);
TetheringConstants.EXTRA_RUN_PROVISION);
if (provisionApp == null || provisionApp.length < 2) { if (provisionApp == null || provisionApp.length < 2) {
final Resources res = Utils.getResourcesForSubId(this, subId); final Resources res = Utils.getResourcesForSubId(this, subId);
provisionApp = res.getStringArray( provisionApp = res.getStringArray(
@@ -77,8 +79,8 @@ public class TetherProvisioningActivity extends Activity {
final Intent intent = new Intent(Intent.ACTION_MAIN); final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(provisionApp[0], provisionApp[1]); intent.setClassName(provisionApp[0], provisionApp[1]);
intent.putExtra(EXTRA_TETHER_TYPE, tetherType); intent.putExtra(EXTRA_TETHER_TYPE, tetherType);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId); intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, mResultReceiver); intent.putExtra(EXTRA_PROVISION_CALLBACK, mResultReceiver);
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]); Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]);
} }
@@ -86,7 +88,7 @@ public class TetherProvisioningActivity extends Activity {
if (getPackageManager().queryIntentActivities(intent, if (getPackageManager().queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) { PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
Log.e(TAG, "Provisioning app is configured, but not available."); 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(); finish();
return; return;
} }
@@ -99,9 +101,8 @@ public class TetherProvisioningActivity extends Activity {
super.onActivityResult(requestCode, resultCode, intent); super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == PROVISION_REQUEST) { if (requestCode == PROVISION_REQUEST) {
if (DEBUG) Log.d(TAG, "Got result from app: " + resultCode); if (DEBUG) Log.d(TAG, "Got result from app: " + resultCode);
int result = resultCode == Activity.RESULT_OK ? int result = resultCode == Activity.RESULT_OK
TetheringManager.TETHER_ERROR_NO_ERROR : ? TETHER_ERROR_NO_ERROR : TETHER_ERROR_PROVISIONING_FAILED;
TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
mResultReceiver.send(result, null); mResultReceiver.send(result, null);
finish(); finish();
} }

View File

@@ -20,7 +20,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.media.RoutingSessionInfo; import android.media.RoutingSessionInfo;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -136,11 +135,6 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { 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(() -> { ThreadUtils.postOnBackgroundThread(() -> {
mLocalMediaManager.adjustSessionVolume(preference.getKey(), (int) newValue); mLocalMediaManager.adjustSessionVolume(preference.getKey(), (int) newValue);
}); });
@@ -184,6 +178,5 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
@Override @Override
public void onSelectedDeviceStateChanged(MediaDevice device, int state) { public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
} }
} }

View File

@@ -821,6 +821,14 @@ public class ChooseLockGeneric extends SettingsActivity {
@Override @Override
public void onDestroy() { public void onDestroy() {
super.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 @Override

View File

@@ -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() { protected int getStageType() {
return mForFingerprint ? Stage.TYPE_FINGERPRINT : return mForFingerprint ? Stage.TYPE_FINGERPRINT :
mForFace ? Stage.TYPE_FACE : mForFace ? Stage.TYPE_FACE :

View File

@@ -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) { protected Intent getRedactionInterstitialIntent(Context context) {
return RedactionInterstitial.createStartIntent(context, mUserId); return RedactionInterstitial.createStartIntent(context, mUserId);
} }

View File

@@ -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 @Override
public void finish() { public void finish() {
super.finish(); super.finish();

View File

@@ -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() { private int getDefaultHeader() {
if (mFrp) { if (mFrp) {
return mIsAlpha ? R.string.lockpassword_confirm_your_password_header_frp return mIsAlpha ? R.string.lockpassword_confirm_your_password_header_frp

View File

@@ -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;
}
}
}

View File

@@ -16,15 +16,24 @@
package com.android.settings.wifi.tether; 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.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.app.usage.UsageStatsManager; 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.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -33,10 +42,9 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.ConnectivityManager; import android.net.TetheringManager;
import android.os.IBinder; import android.os.IBinder;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.os.SystemClock;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
@@ -74,7 +82,6 @@ public class TetherService extends Service {
private TetherServiceWrapper mWrapper; private TetherServiceWrapper mWrapper;
private ArrayList<Integer> mCurrentTethers; private ArrayList<Integer> mCurrentTethers;
private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks; private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
private HotspotOffReceiver mHotspotReceiver;
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
@@ -93,18 +100,16 @@ public class TetherService extends Service {
mCurrentTethers = stringToTethers(prefs.getString(KEY_TETHERS, "")); mCurrentTethers = stringToTethers(prefs.getString(KEY_TETHERS, ""));
mCurrentTypeIndex = 0; mCurrentTypeIndex = 0;
mPendingCallbacks = new ArrayMap<>(3); mPendingCallbacks = new ArrayMap<>(3);
mPendingCallbacks.put(ConnectivityManager.TETHERING_WIFI, new ArrayList<ResultReceiver>()); mPendingCallbacks.put(TETHERING_WIFI, new ArrayList<ResultReceiver>());
mPendingCallbacks.put(ConnectivityManager.TETHERING_USB, new ArrayList<ResultReceiver>()); mPendingCallbacks.put(TETHERING_USB, new ArrayList<ResultReceiver>());
mPendingCallbacks.put( mPendingCallbacks.put(TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>());
ConnectivityManager.TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>()); mPendingCallbacks.put(TETHERING_ETHERNET, new ArrayList<ResultReceiver>());
mHotspotReceiver = new HotspotOffReceiver(this);
} }
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.hasExtra(EXTRA_SUBID)) { if (intent.hasExtra(EXTRA_SUBID)) {
final int tetherSubId = intent.getIntExtra(EXTRA_SUBID, final int tetherSubId = intent.getIntExtra(EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId(); final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
if (tetherSubId != subId) { if (tetherSubId != subId) {
Log.e(TAG, "This Provisioning request is outdated, current subId: " + 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; return START_NOT_STICKY;
} }
} }
if (intent.hasExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE)) { if (intent.hasExtra(EXTRA_ADD_TETHER_TYPE)) {
int type = intent.getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, int type = intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID);
ConnectivityManager.TETHERING_INVALID); ResultReceiver callback = intent.getParcelableExtra(EXTRA_PROVISION_CALLBACK);
ResultReceiver callback =
intent.getParcelableExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK);
if (callback != null) { if (callback != null) {
List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type); List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type);
if (callbacksForType != null) { if (callbacksForType != null) {
callbacksForType.add(callback); callbacksForType.add(callback);
} else { } else {
// Invalid tether type. Just ignore this request and report failure. // 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(); stopSelf();
return START_NOT_STICKY; 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) { if (!mInProvisionCheck) {
int type = intent.getIntExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, int type = intent.getIntExtra(EXTRA_REM_TETHER_TYPE, TETHERING_INVALID);
ConnectivityManager.TETHERING_INVALID);
int index = mCurrentTethers.indexOf(type); int index = mCurrentTethers.indexOf(type);
if (DEBUG) Log.d(TAG, "Removing tether " + type + ", index " + index); if (DEBUG) Log.d(TAG, "Removing tether " + type + ", index " + index);
if (index >= 0) { if (index >= 0) {
removeTypeAtIndex(index); removeTypeAtIndex(index);
} }
cancelAlarmIfNecessary();
} else { } 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, if (intent.getBooleanExtra(EXTRA_RUN_PROVISION, false)) {
// 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)) {
startProvisioning(mCurrentTypeIndex); startProvisioning(mCurrentTypeIndex);
} else if (!mInProvisionCheck) { } else if (!mInProvisionCheck) {
// If we aren't running any provisioning, no reason to stay alive. // 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); SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
prefs.edit().putString(KEY_TETHERS, tethersToString(mCurrentTethers)).commit(); prefs.edit().putString(KEY_TETHERS, tethersToString(mCurrentTethers)).commit();
unregisterReceivers(); unregisterReceiver(mReceiver);
if (DEBUG) Log.d(TAG, "Destroying TetherService"); if (DEBUG) Log.d(TAG, "Destroying TetherService");
super.onDestroy(); super.onDestroy();
} }
private void unregisterReceivers() {
unregisterReceiver(mReceiver);
mHotspotReceiver.unregister();
}
private void removeTypeAtIndex(int index) { private void removeTypeAtIndex(int index) {
mCurrentTethers.remove(index); mCurrentTethers.remove(index);
// If we are currently in the middle of a check, we may need to adjust the // 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) { private ArrayList<Integer> stringToTethers(String tethersStr) {
ArrayList<Integer> ret = new ArrayList<Integer>(); ArrayList<Integer> ret = new ArrayList<Integer>();
if (TextUtils.isEmpty(tethersStr)) return ret; if (TextUtils.isEmpty(tethersStr)) return ret;
@@ -231,32 +214,9 @@ public class TetherService extends Service {
return buffer.toString(); return buffer.toString();
} }
private void disableWifiTethering() { private void disableTethering(final int tetheringType) {
ConnectivityManager cm = final TetheringManager tm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); tm.stopTethering(tetheringType);
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 startProvisioning(int index) { private void startProvisioning(int index) {
@@ -279,7 +239,7 @@ public class TetherService extends Service {
Intent intent = new Intent(provisionAction); Intent intent = new Intent(provisionAction);
int type = mCurrentTethers.get(index); int type = mCurrentTethers.get(index);
intent.putExtra(TETHER_CHOICE, type); 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.setFlags(Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); | 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) { private void fireCallbacksForType(int type, int result) {
List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type); List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type);
if (callbacksForType == null) { if (callbacksForType == null) {
return; return;
} }
int errorCode = result == RESULT_OK ? ConnectivityManager.TETHER_ERROR_NO_ERROR : int errorCode = result == RESULT_OK ? TETHER_ERROR_NO_ERROR :
ConnectivityManager.TETHER_ERROR_PROVISION_FAILED; TETHER_ERROR_PROVISIONING_FAILED;
for (ResultReceiver callback : callbacksForType) { for (ResultReceiver callback : callbacksForType) {
if (DEBUG) Log.d(TAG, "Firing result: " + errorCode + " to callback"); if (DEBUG) Log.d(TAG, "Firing result: " + errorCode + " to callback");
callback.send(errorCode, null); callback.send(errorCode, null);
@@ -375,19 +293,7 @@ public class TetherService extends Service {
int checkType = mCurrentTethers.get(mCurrentTypeIndex); int checkType = mCurrentTethers.get(mCurrentTypeIndex);
mInProvisionCheck = false; mInProvisionCheck = false;
int result = intent.getIntExtra(EXTRA_RESULT, RESULT_DEFAULT); int result = intent.getIntExtra(EXTRA_RESULT, RESULT_DEFAULT);
if (result != RESULT_OK) { if (result != RESULT_OK) disableTethering(checkType);
switch (checkType) {
case ConnectivityManager.TETHERING_WIFI:
disableWifiTethering();
break;
case ConnectivityManager.TETHERING_BLUETOOTH:
disableBtTethering();
break;
case ConnectivityManager.TETHERING_USB:
disableUsbTethering();
break;
}
}
fireCallbacksForType(checkType, result); fireCallbacksForType(checkType, result);
if (++mCurrentTypeIndex >= mCurrentTethers.size()) { if (++mCurrentTypeIndex >= mCurrentTethers.size()) {

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -16,27 +16,23 @@
package com.android.settings.wifi.tether; package com.android.settings.wifi.tether;
import static android.net.ConnectivityManager.EXTRA_ADD_TETHER_TYPE; import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
import static android.net.ConnectivityManager.EXTRA_PROVISION_CALLBACK; import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
import static android.net.ConnectivityManager.EXTRA_REM_TETHER_TYPE; import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
import static android.net.ConnectivityManager.EXTRA_RUN_PROVISION; import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.ConnectivityManager.EXTRA_SET_ALARM; import static android.net.TetheringManager.TETHERING_INVALID;
import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_USB;
import static android.net.ConnectivityManager.TETHERING_INVALID; import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.ConnectivityManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.Activity; import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -51,7 +47,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.ConnectivityManager; import android.net.TetheringManager;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.ResultReceiver; import android.os.ResultReceiver;
@@ -92,8 +88,7 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
private ProvisionReceiver mProvisionReceiver; private ProvisionReceiver mProvisionReceiver;
private Receiver mResultReceiver; private Receiver mResultReceiver;
@Mock private AlarmManager mAlarmManager; @Mock private TetheringManager mTetheringManager;
@Mock private ConnectivityManager mConnectivityManager;
@Mock private PackageManager mPackageManager; @Mock private PackageManager mPackageManager;
@Mock private WifiManager mWifiManager; @Mock private WifiManager mWifiManager;
@Mock private SharedPreferences mPrefs; @Mock private SharedPreferences mPrefs;
@@ -158,15 +153,6 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
super.tearDown(); 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() { public void testStartForProvision() {
runProvisioningForType(TETHERING_WIFI); runProvisioningForType(TETHERING_WIFI);
@@ -184,19 +170,6 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
assertTrue(mWrapper.isAppInactive(FAKE_PACKAGE_NAME)); 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() { public void testStartMultiple() {
runProvisioningForType(TETHERING_WIFI); runProvisioningForType(TETHERING_WIFI);
@@ -235,9 +208,9 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
runProvisioningForType(TETHERING_WIFI); runProvisioningForType(TETHERING_WIFI);
assertTrue(waitForProvisionRequest(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() { public void testFailureStopsTethering_Usb() {
@@ -246,24 +219,9 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
runProvisioningForType(TETHERING_USB); runProvisioningForType(TETHERING_USB);
assertTrue(waitForProvisionRequest(TETHERING_USB)); assertTrue(waitForProvisionRequest(TETHERING_USB));
assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED)); assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISIONING_FAILED));
verify(mConnectivityManager).setUsbTethering(eq(false)); verify(mTetheringManager).stopTethering(TETHERING_USB);
}
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());
} }
public void testIgnoreOutdatedRequest() { public void testIgnoreOutdatedRequest() {
@@ -387,10 +345,8 @@ public class TetherServiceTest extends ServiceTestCase<TetherService> {
@Override @Override
public Object getSystemService(String name) { public Object getSystemService(String name) {
if (ALARM_SERVICE.equals(name)) { if (TETHERING_SERVICE.equals(name)) {
return mAlarmManager; return mTetheringManager;
} else if (CONNECTIVITY_SERVICE.equals(name)) {
return mConnectivityManager;
} else if (WIFI_SERVICE.equals(name)) { } else if (WIFI_SERVICE.equals(name)) {
return mWifiManager; return mWifiManager;
} }