1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.car.settings.wifi;
17
18import android.net.NetworkInfo.State;
19import android.net.wifi.WifiManager;
20import android.os.Bundle;
21import android.support.annotation.StringRes;
22import android.view.View;
23import android.widget.Button;
24import android.widget.TextView;
25import android.widget.Toast;
26
27import com.android.car.list.SimpleTextLineItem;
28import com.android.car.list.TypedPagedListAdapter;
29import com.android.car.settings.R;
30import com.android.car.settings.common.ListSettingsFragment;
31import com.android.car.settings.common.Logger;
32import com.android.settingslib.wifi.AccessPoint;
33
34import java.util.ArrayList;
35
36/**
37 * Shows details about a wifi network, including actions related to the network,
38 * e.g. ignore, disconnect, etc. The intent should include information about
39 * access point, use that to render UI, e.g. show SSID etc.
40 */
41public class WifiDetailFragment extends ListSettingsFragment {
42    public static final String EXTRA_AP_STATE = "extra_ap_state";
43    private static final Logger LOG = new Logger(WifiDetailFragment.class);
44
45    private AccessPoint mAccessPoint;
46    private WifiManager mWifiManager;
47
48    private class ActionFailListener implements WifiManager.ActionListener {
49        @StringRes
50        private final int mMessageResId;
51
52        public ActionFailListener(@StringRes int messageResId) {
53            mMessageResId = messageResId;
54        }
55
56        @Override
57        public void onSuccess() {
58        }
59
60        @Override
61        public void onFailure(int reason) {
62            Toast.makeText(getContext(),
63                    R.string.wifi_failed_connect_message,
64                    Toast.LENGTH_SHORT).show();
65        }
66    }
67
68    public static WifiDetailFragment getInstance(AccessPoint accessPoint) {
69        WifiDetailFragment wifiDetailFragment = new WifiDetailFragment();
70        Bundle bundle = ListSettingsFragment.getBundle();
71        bundle.putInt(EXTRA_TITLE_ID, R.string.wifi_settings);
72        bundle.putInt(EXTRA_ACTION_BAR_LAYOUT, R.layout.action_bar_with_button);
73        Bundle accessPointState = new Bundle();
74        accessPoint.saveWifiState(accessPointState);
75        bundle.putBundle(EXTRA_AP_STATE, accessPointState);
76        wifiDetailFragment.setArguments(bundle);
77        return wifiDetailFragment;
78    }
79
80    @Override
81    public void onCreate(Bundle savedInstanceState) {
82        super.onCreate(savedInstanceState);
83        mAccessPoint = new AccessPoint(getContext(), getArguments().getBundle(EXTRA_AP_STATE));
84    }
85
86    @Override
87    public void onActivityCreated(Bundle savedInstanceState) {
88        mWifiManager = getContext().getSystemService(WifiManager.class);
89
90        super.onActivityCreated(savedInstanceState);
91        ((TextView) getActivity().findViewById(R.id.title)).setText(mAccessPoint.getSsid());
92        Button forgetButton = (Button) getActivity().findViewById(R.id.action_button1);
93        forgetButton.setText(R.string.forget);
94        forgetButton.setOnClickListener(v -> {
95            forget();
96            getFragmentController().goBack();
97        });
98
99        if (mAccessPoint.isSaved() && !mAccessPoint.isActive()) {
100            Button connectButton = (Button) getActivity().findViewById(R.id.action_button2);
101            connectButton.setVisibility(View.VISIBLE);
102            connectButton.setText(R.string.wifi_setup_connect);
103            connectButton.setOnClickListener(v -> {
104                mWifiManager.connect(mAccessPoint.getConfig(),
105                        new ActionFailListener(R.string.wifi_failed_connect_message));
106                getFragmentController().goBack();
107            });
108        }
109    }
110
111    @Override
112    public ArrayList<TypedPagedListAdapter.LineItem> getLineItems() {
113        ArrayList<TypedPagedListAdapter.LineItem> lineItems = new ArrayList<>();
114        lineItems.add(
115                new SimpleTextLineItem(getText(R.string.wifi_status), mAccessPoint.getSummary()));
116        lineItems.add(
117                new SimpleTextLineItem(getText(R.string.wifi_signal), getSignalString()));
118        lineItems.add(new SimpleTextLineItem(getText(R.string.wifi_security),
119                mAccessPoint.getSecurityString(/* concise= */ true)));
120        return lineItems;
121    }
122
123    private String getSignalString() {
124        String[] signalStrings = getResources().getStringArray(R.array.wifi_signals);
125
126        int level = WifiManager.calculateSignalLevel(
127                mAccessPoint.getRssi(), signalStrings.length);
128        return signalStrings[level];
129    }
130
131    private void forget() {
132        if (!mAccessPoint.isSaved()) {
133            if (mAccessPoint.getNetworkInfo() != null &&
134                    mAccessPoint.getNetworkInfo().getState() != State.DISCONNECTED) {
135                // Network is active but has no network ID - must be ephemeral.
136                mWifiManager.disableEphemeralNetwork(
137                        AccessPoint.convertToQuotedString(mAccessPoint.getSsidStr()));
138            } else {
139                // Should not happen, but a monkey seems to trigger it
140                LOG.e("Failed to forget invalid network " + mAccessPoint.getConfig());
141                return;
142            }
143        } else {
144            mWifiManager.forget(mAccessPoint.getConfig().networkId,
145                    new ActionFailListener(R.string.wifi_failed_forget_message));
146        }
147    }
148}
149