Apparently when the device is idle long enough the system will clean up the dialog view for the hotspot band preference. This will cause restore state to fail once it decides to pause the activity. To avoid this we should make sure the boxes are not null. Test: robotest Bug: 78445411 Change-Id: I2a82b01f894f62be6c5209c78faddc4089aa6301
259 lines
8.8 KiB
Java
259 lines
8.8 KiB
Java
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package com.android.settings.widget;
|
|
|
|
import android.app.AlertDialog;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.net.wifi.WifiConfiguration;
|
|
import android.os.Bundle;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
import android.support.annotation.VisibleForTesting;
|
|
import android.util.AttributeSet;
|
|
import android.view.View;
|
|
import android.widget.Button;
|
|
import android.widget.CheckBox;
|
|
import android.widget.CompoundButton;
|
|
import android.widget.LinearLayout;
|
|
|
|
import com.android.settings.R;
|
|
import com.android.settingslib.CustomDialogPreference;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
public class HotspotApBandSelectionPreference extends CustomDialogPreference implements
|
|
CompoundButton.OnCheckedChangeListener, DialogInterface.OnShowListener {
|
|
private static final int UNSET = Integer.MIN_VALUE;
|
|
|
|
@VisibleForTesting
|
|
static final String KEY_CHECKED_BANDS = "checked_bands";
|
|
@VisibleForTesting
|
|
static final String KEY_HOTSPOT_SUPER_STATE = "hotspot_super_state";
|
|
|
|
@VisibleForTesting
|
|
CheckBox mBox2G;
|
|
@VisibleForTesting
|
|
CheckBox mBox5G;
|
|
@VisibleForTesting
|
|
ArrayList<Integer> mRestoredBands;
|
|
@VisibleForTesting
|
|
boolean mShouldRestore;
|
|
|
|
private String[] mBandEntries;
|
|
private int mExistingConfigValue = UNSET;
|
|
|
|
public HotspotApBandSelectionPreference(Context context) {
|
|
super(context);
|
|
}
|
|
|
|
public HotspotApBandSelectionPreference(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
}
|
|
|
|
public HotspotApBandSelectionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
}
|
|
|
|
public HotspotApBandSelectionPreference(Context context, AttributeSet attrs, int defStyleAttr,
|
|
int defStyleRes) {
|
|
super(context, attrs, defStyleAttr, defStyleRes);
|
|
}
|
|
|
|
@Override
|
|
protected void onRestoreInstanceState(Parcelable state) {
|
|
SavedState myState = (SavedState) state;
|
|
|
|
super.onRestoreInstanceState(myState.getSuperState());
|
|
|
|
mShouldRestore = myState.shouldRestore;
|
|
if (mShouldRestore) {
|
|
mRestoredBands = new ArrayList<>();
|
|
if (myState.enabled2G) {
|
|
mRestoredBands.add(WifiConfiguration.AP_BAND_2GHZ);
|
|
}
|
|
if (myState.enabled5G) {
|
|
mRestoredBands.add(WifiConfiguration.AP_BAND_5GHZ);
|
|
}
|
|
} else {
|
|
mRestoredBands = null;
|
|
}
|
|
updatePositiveButton();
|
|
}
|
|
|
|
@Override
|
|
protected void onBindDialogView(View view) {
|
|
super.onBindDialogView(view);
|
|
final Context context = getContext();
|
|
|
|
// Register so we can adjust the buttons if needed once the dialog is available.
|
|
setOnShowListener(this);
|
|
|
|
mBandEntries = context.getResources().getStringArray(R.array.wifi_ap_band_config_full);
|
|
// add a checkbox for every band entry.
|
|
addApBandViews((LinearLayout) view);
|
|
// try to update the button just in case we already missed the onShow call.
|
|
updatePositiveButton();
|
|
// clear any saved state so it doesn't leak across multiple rotations/dialog closings
|
|
mRestoredBands = null;
|
|
mShouldRestore = false;
|
|
}
|
|
|
|
@Override
|
|
protected Parcelable onSaveInstanceState() {
|
|
final Parcelable superState = super.onSaveInstanceState();
|
|
|
|
SavedState myState = new SavedState(superState);
|
|
myState.shouldRestore = getDialog() != null;
|
|
myState.enabled2G = mBox2G != null && mBox2G.isChecked();
|
|
myState.enabled5G = mBox5G != null && mBox5G.isChecked();
|
|
return myState;
|
|
}
|
|
|
|
@Override
|
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
if (!(buttonView instanceof CheckBox)) {
|
|
return;
|
|
}
|
|
updatePositiveButton();
|
|
}
|
|
|
|
@Override
|
|
protected void onClick(DialogInterface dialog, int which) {
|
|
// we only want to persist our enabled bands if apply is clicked
|
|
if (which == DialogInterface.BUTTON_POSITIVE) {
|
|
if (mBox2G.isChecked() || mBox5G.isChecked()) {
|
|
int wifiBand = getWifiBand();
|
|
mExistingConfigValue = wifiBand;
|
|
callChangeListener(wifiBand);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Used to set the band selection for the preference if one already exists
|
|
* @param band the band to set it to from {@link WifiConfiguration}
|
|
*/
|
|
public void setExistingConfigValue(int band) {
|
|
mExistingConfigValue = band;
|
|
}
|
|
|
|
private void addApBandViews(LinearLayout view) {
|
|
mBox2G = view.findViewById(R.id.box_2g);
|
|
mBox2G.setText(mBandEntries[WifiConfiguration.AP_BAND_2GHZ]);
|
|
mBox2G.setChecked(restoreBandIfNeeded(WifiConfiguration.AP_BAND_2GHZ));
|
|
mBox2G.setOnCheckedChangeListener(this);
|
|
|
|
mBox5G = view.findViewById(R.id.box_5g);
|
|
mBox5G.setText(mBandEntries[WifiConfiguration.AP_BAND_5GHZ]);
|
|
mBox5G.setChecked(restoreBandIfNeeded(WifiConfiguration.AP_BAND_5GHZ));
|
|
mBox5G.setOnCheckedChangeListener(this);
|
|
}
|
|
|
|
private boolean restoreBandIfNeeded(int band) {
|
|
// Only use the provided config if we aren't restoring, restore if state available
|
|
return (isBandPreviouslySelected(band) && !mShouldRestore)
|
|
|| (mShouldRestore && mRestoredBands.contains(band));
|
|
}
|
|
|
|
private void updatePositiveButton() {
|
|
AlertDialog dialog = (AlertDialog) getDialog();
|
|
Button button = dialog == null ? null : dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
|
if (button != null && mBox5G != null && mBox2G != null) {
|
|
button.setEnabled(mBox2G.isChecked() || mBox5G.isChecked());
|
|
}
|
|
}
|
|
|
|
@VisibleForTesting
|
|
int getWifiBand() {
|
|
final boolean checked_2g = mBox2G.isChecked();
|
|
final boolean checked_5g = mBox5G.isChecked();
|
|
if (checked_2g && checked_5g) {
|
|
return WifiConfiguration.AP_BAND_ANY;
|
|
} else if (checked_2g && !checked_5g) {
|
|
return WifiConfiguration.AP_BAND_2GHZ;
|
|
} else if (checked_5g && !checked_2g) {
|
|
return WifiConfiguration.AP_BAND_5GHZ;
|
|
} else {
|
|
throw new IllegalStateException("Wifi Config only supports selecting one or all bands");
|
|
}
|
|
}
|
|
|
|
private boolean isBandPreviouslySelected(int bandIndex) {
|
|
switch(mExistingConfigValue) {
|
|
case WifiConfiguration.AP_BAND_ANY:
|
|
return true;
|
|
case WifiConfiguration.AP_BAND_2GHZ:
|
|
return bandIndex == 0;
|
|
case WifiConfiguration.AP_BAND_5GHZ:
|
|
return bandIndex == 1;
|
|
case UNSET:
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onShow(DialogInterface dialog) {
|
|
updatePositiveButton();
|
|
}
|
|
|
|
private static class SavedState extends BaseSavedState {
|
|
boolean shouldRestore;
|
|
boolean enabled2G;
|
|
boolean enabled5G;
|
|
|
|
public SavedState(Parcelable source) {
|
|
super(source);
|
|
}
|
|
|
|
private SavedState(Parcel in) {
|
|
super(in);
|
|
shouldRestore = in.readByte() == 1;
|
|
enabled2G = in.readByte() == 1;
|
|
enabled5G = in.readByte() == 1;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
super.writeToParcel(dest, flags);
|
|
dest.writeByte((byte) (shouldRestore ? 1 : 0));
|
|
dest.writeByte((byte) (enabled2G ? 1: 0));
|
|
dest.writeByte((byte) (enabled5G ? 1 : 0));
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "HotspotApBandSelectionPreference.SavedState{"
|
|
+ Integer.toHexString(System.identityHashCode(this))
|
|
+ " shouldRestore=" + shouldRestore
|
|
+ " enabled2G=" + enabled2G
|
|
+ " enabled5G=" + enabled5G + "}";
|
|
}
|
|
|
|
public static final Parcelable.Creator<SavedState> CREATOR
|
|
= new Parcelable.Creator<SavedState>() {
|
|
public SavedState createFromParcel(Parcel in) {
|
|
return new SavedState(in);
|
|
}
|
|
|
|
public SavedState[] newArray(int size) {
|
|
return new SavedState[size];
|
|
}
|
|
};
|
|
}
|
|
}
|