blob: 3ffb851f62ad83a8a9dad0c2cbcafc2b2e7a9c5f [file] [log] [blame]
/*
* Copyright (C) 2021 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.google.android.car.networking.preferenceupdater.fragments;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
import android.content.Context;
import android.net.NetworkIdentity;
import android.net.NetworkTemplate;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkSuggestion;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import com.google.android.car.networking.preferenceupdater.R;
import com.google.android.car.networking.preferenceupdater.components.CarDriverDistractionManagerAdapter;
import com.google.android.car.networking.preferenceupdater.components.MetricDisplay;
import com.google.android.car.networking.preferenceupdater.components.OemNetworkPreferencesAdapter;
import com.google.android.car.networking.preferenceupdater.components.PersonalStorage;
import com.google.android.car.networking.preferenceupdater.utils.Utils;
import java.util.ArrayList;
import java.util.Set;
public final class ManagerFragment extends Fragment {
private static final String TAG = ManagerFragment.class.getSimpleName();
public static final String METRIC_MSG_OEM_PREFERENCE_KEY = "oem_preference";
public static final String METRIC_MSG_OEM_PREFERENCE_TX_KEY = "oem_preference_tx";
public static final String METRIC_MSG_OEM_PREFERENCE_RX_KEY = "oem_preference_rx";
private PersonalStorage mPersonalStorage;
private OemNetworkPreferencesAdapter mOemNetworkPreferencesAdapter;
private CarDriverDistractionManagerAdapter mCarDriverDistractionManagerAdapter;
private WifiManager mWifiManager;
// Metric Display components
private MetricDisplay mMetricDisplay;
private TextView mOemPaidRxBytesTextView;
private TextView mOemPaidTxBytesTextView;
private TextView mOemPrivateRxBytesTextView;
private TextView mOemPrivateTxBytesTextView;
private TextView mOemTotalRxBytesTextView;
private TextView mOemTotalTxBytesTextView;
// Metric display handler that updates indicators
public final Handler mMetricMessageHandler =
new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
int oem_preference = bundle.getInt(METRIC_MSG_OEM_PREFERENCE_KEY);
long tx = bundle.getLong(METRIC_MSG_OEM_PREFERENCE_TX_KEY);
long rx = bundle.getLong(METRIC_MSG_OEM_PREFERENCE_RX_KEY);
updateMetricIndicatorByType(oem_preference, tx, rx);
}
};
private EditText mOEMPaidAppsEditText;
private EditText mOEMPaidNoFallbackAppsEditText;
private EditText mOEMPaidOnlyAppsEditText;
private EditText mOEMPrivateOnlyAppsEditText;
private TextView mCurrentPANSStatusTextView;
private Switch mReapplyPANSOnBootSwitch;
private Button mApplyConfigurationBtn;
private Button mResetNetworkPreferencesBtn;
private Button mApplyWifiCapabilitiesBtn;
// Wifi SSIDs
private EditText mOEMPaidWifiSSIDsEditText;
private EditText mOEMPrivateWifiSSIDsEditText;
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.manager, container, false);
Context context = getActivity();
mPersonalStorage = new PersonalStorage(context);
mOemNetworkPreferencesAdapter = new OemNetworkPreferencesAdapter(context);
mCarDriverDistractionManagerAdapter = new CarDriverDistractionManagerAdapter(context);
mMetricDisplay = new MetricDisplay(context, mMetricMessageHandler);
defineViewsFromFragment(v);
defineButtonActions();
setDefaultValues();
// When we start app for the first time, means it never applied any PANS policies.
// Set the text to false.
updatePansPolicyInEffectStatus(false);
// Let's start watching OEM traffic and updating indicators
mMetricDisplay.startWatching();
mWifiManager = context.getSystemService(WifiManager.class);
return v;
}
@Override
public void onDestroyView() {
super.onDestroyView();
mMetricDisplay.stopWatching();
mCarDriverDistractionManagerAdapter.destroy();
}
/** Finds all views on the fragments and stores them in instance variables */
private void defineViewsFromFragment(View v) {
mOEMPaidAppsEditText = v.findViewById(R.id.OEMPaidAppsEditText);
mOEMPaidNoFallbackAppsEditText = v.findViewById(R.id.OEMPaidNoFallbackAppsEditText);
mOEMPaidOnlyAppsEditText = v.findViewById(R.id.OEMPaidOnlyAppsEditText);
mOEMPrivateOnlyAppsEditText = v.findViewById(R.id.OEMPrivateOnlyAppsEditText);
mOEMPaidWifiSSIDsEditText = v.findViewById(R.id.OEMPaidWifiSSIDsEditText);
mOEMPrivateWifiSSIDsEditText = v.findViewById(R.id.OEMPrivateWifiSSIDsEditText);
mCurrentPANSStatusTextView = v.findViewById(R.id.currentPANSStatusTextView);
mReapplyPANSOnBootSwitch = v.findViewById(R.id.reapplyPANSOnBootSwitch);
mApplyConfigurationBtn = v.findViewById(R.id.applyConfigurationBtn);
mResetNetworkPreferencesBtn = v.findViewById(R.id.resetNetworkPreferencesBtn);
mApplyWifiCapabilitiesBtn = v.findViewById(R.id.applyWifiCapabilitiesButton);
// Since our Metric Display is going to be alive, we want to pass our TextView components
// into MetricDisplay instance to simplify refresh logic.
mOemPaidRxBytesTextView = v.findViewById(R.id.oemPaidRxBytesTextView);
mOemPaidTxBytesTextView = v.findViewById(R.id.oemPaidTxBytesTextView);
mOemPrivateRxBytesTextView = v.findViewById(R.id.oemPrivateRxBytesTextView);
mOemPrivateTxBytesTextView = v.findViewById(R.id.oemPrivateTxBytesTextView);
mOemTotalRxBytesTextView = v.findViewById(R.id.totalOemManagedRxBytesTextView);
mOemTotalTxBytesTextView = v.findViewById(R.id.totalOemManagedTxBytesTextView);
mMetricDisplay.setMainActivity(this);
}
private void updateMetricIndicatorByType(int type, long tx, long rx) {
switch (type) {
case NetworkIdentity.OEM_PAID:
mOemPaidTxBytesTextView.setText(String.valueOf(tx));
mOemPaidRxBytesTextView.setText(String.valueOf(rx));
break;
case NetworkIdentity.OEM_PRIVATE:
mOemPrivateTxBytesTextView.setText(String.valueOf(tx));
mOemPrivateRxBytesTextView.setText(String.valueOf(rx));
break;
case NetworkTemplate.OEM_MANAGED_YES:
mOemTotalTxBytesTextView.setText(String.valueOf(tx));
mOemTotalRxBytesTextView.setText(String.valueOf(rx));
break;
default:
Log.e(TAG, "Unknown NetworkIdentity " + type);
}
}
/** Defines actions of the buttons on the page */
private void defineButtonActions() {
mApplyConfigurationBtn.setOnClickListener(view -> onApplyConfigurationBtnClick());
mApplyWifiCapabilitiesBtn.setOnClickListener(view -> onApplyWifiCapabilitiesBtnClick());
mReapplyPANSOnBootSwitch.setOnCheckedChangeListener(
(buttonView, isChecked) ->
mPersonalStorage.saveReapplyPansOnBootCompleteState(true));
mResetNetworkPreferencesBtn.setOnClickListener(view -> resetNetworkPreferences());
}
private void resetNetworkPreferences() {
mOemNetworkPreferencesAdapter.resetNetworkPreferences();
mPersonalStorage.resetNetworkPreferences();
setDefaultValues();
}
/** Sets default values of text fields */
private void setDefaultValues() {
mOEMPaidAppsEditText.setText(getFromStorage(OEM_NETWORK_PREFERENCE_OEM_PAID));
mOEMPaidNoFallbackAppsEditText.setText(
getFromStorage(OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK));
mOEMPaidOnlyAppsEditText.setText(getFromStorage(OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY));
mOEMPrivateOnlyAppsEditText.setText(
getFromStorage(OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY));
mReapplyPANSOnBootSwitch.setChecked(mPersonalStorage.getReapplyPansOnBootCompleteState());
mOEMPaidWifiSSIDsEditText.setText(Utils.toString(mPersonalStorage.getOemPaidWifiSsids()));
mOEMPrivateWifiSSIDsEditText.setText(
Utils.toString(mPersonalStorage.getOemPrivateWifiSsids()));
}
private String getFromStorage(int type) {
return Utils.toString(mPersonalStorage.get(type));
}
// TODO(178245727): This should be updated once ag/13587171 merged.
private void updatePansPolicyInEffectStatus(boolean status) {
// Whenever we apply PANS logic, we save it to the PersonalStorage. Meaning we can use
// PersonalStorage as the check for having any policy set or not.
mCurrentPANSStatusTextView.setText(status ? "Yes" : "No");
}
private void onApplyWifiCapabilitiesBtnClick() {
Log.d(TAG, "Applying WiFi settings");
Set<String> ssidsWithOemPaid = Utils.toSet(mOEMPaidWifiSSIDsEditText.getText().toString());
Set<String> ssidsWithOemPrivate =
Utils.toSet(mOEMPrivateWifiSSIDsEditText.getText().toString());
try {
ArrayList<WifiNetworkSuggestion> list = new ArrayList<>();
for (String ssid : ssidsWithOemPaid) {
list.add(
new WifiNetworkSuggestion.Builder()
.setSsid(WifiInfo.sanitizeSsid(ssid))
.setOemPaid(true)
.build());
}
for (String ssid : ssidsWithOemPrivate) {
list.add(
new WifiNetworkSuggestion.Builder()
.setSsid(WifiInfo.sanitizeSsid(ssid))
.setOemPrivate(true)
.build());
}
mWifiManager.removeNetworkSuggestions(new ArrayList<>());
mWifiManager.addNetworkSuggestions(list);
} catch (Exception e) {
// Could not set Wifi capabilities, pop the toast and do nothing
Log.e(TAG, "Failed to set Wifi capabilities", e);
Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_SHORT).show();
return;
}
mPersonalStorage.storeWifi(ssidsWithOemPaid, ssidsWithOemPrivate);
}
private void onApplyConfigurationBtnClick() {
Log.d(TAG, "Applying PANS");
// First we want to make sure that we are allowed to change
if (!mCarDriverDistractionManagerAdapter.allowedToBeDistracted()) {
// We are not allowed to apply PANS changes. Do nothing.
Log.w(TAG, "Network preferences will not be updated, due to Driver Distraction Mode");
return;
}
SparseArray<Set<String>> preference = new SparseArray<>();
preference.put(
OEM_NETWORK_PREFERENCE_OEM_PAID,
Utils.toSet(mOEMPaidAppsEditText.getText().toString()));
preference.put(
OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK,
Utils.toSet(mOEMPaidNoFallbackAppsEditText.getText().toString()));
preference.put(
OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY,
Utils.toSet(mOEMPaidOnlyAppsEditText.getText().toString()));
preference.put(
OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY,
Utils.toSet(mOEMPrivateOnlyAppsEditText.getText().toString()));
mOemNetworkPreferencesAdapter.applyPreference(preference);
// Persist latest preference
mPersonalStorage.store(preference);
// Notify app that PANS policy is now in effect
updatePansPolicyInEffectStatus(true);
}
}