• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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  */
16 
17 package com.android.settings.deviceinfo;
18 
19 import android.annotation.Nullable;
20 import android.content.Context;
21 import android.net.wifi.WifiConfiguration;
22 import android.net.wifi.WifiManager;
23 import android.os.Build;
24 import android.os.Bundle;
25 import android.provider.Settings;
26 import android.support.v7.preference.Preference;
27 import android.support.v7.preference.PreferenceScreen;
28 import android.text.SpannedString;
29 
30 import com.android.internal.annotations.VisibleForTesting;
31 
32 import com.android.settings.bluetooth.BluetoothLengthDeviceNameFilter;
33 import com.android.settings.core.BasePreferenceController;
34 import com.android.settings.widget.ValidatedEditTextPreference;
35 import com.android.settings.wifi.tether.WifiDeviceNameTextValidator;
36 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
37 import com.android.settingslib.bluetooth.LocalBluetoothManager;
38 import com.android.settingslib.core.lifecycle.Lifecycle;
39 import com.android.settingslib.core.lifecycle.LifecycleObserver;
40 import com.android.settingslib.core.lifecycle.events.OnCreate;
41 import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
42 
43 public class DeviceNamePreferenceController extends BasePreferenceController
44         implements ValidatedEditTextPreference.Validator,
45                 Preference.OnPreferenceChangeListener,
46                 LifecycleObserver,
47                 OnSaveInstanceState,
48                 OnCreate {
49     private static final String PREF_KEY = "device_name";
50     public static final int DEVICE_NAME_SET_WARNING_ID = 1;
51     private static final String KEY_PENDING_DEVICE_NAME = "key_pending_device_name";
52     private String mDeviceName;
53     protected WifiManager mWifiManager;
54     private final WifiDeviceNameTextValidator mWifiDeviceNameTextValidator;
55     private ValidatedEditTextPreference mPreference;
56     @Nullable
57     private LocalBluetoothManager mBluetoothManager;
58     private DeviceNamePreferenceHost mHost;
59     private String mPendingDeviceName;
60 
DeviceNamePreferenceController(Context context)61     public DeviceNamePreferenceController(Context context) {
62         super(context, PREF_KEY);
63 
64         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
65         mWifiDeviceNameTextValidator = new WifiDeviceNameTextValidator();
66 
67         initializeDeviceName();
68     }
69 
70     @Override
displayPreference(PreferenceScreen screen)71     public void displayPreference(PreferenceScreen screen) {
72         super.displayPreference(screen);
73         mPreference = (ValidatedEditTextPreference) screen.findPreference(PREF_KEY);
74         final CharSequence deviceName = getSummary();
75         mPreference.setSummary(deviceName);
76         mPreference.setText(deviceName.toString());
77         mPreference.setValidator(this);
78     }
79 
initializeDeviceName()80     private void initializeDeviceName() {
81         mDeviceName = Settings.Global.getString(mContext.getContentResolver(),
82                 Settings.Global.DEVICE_NAME);
83         if (mDeviceName == null) {
84             mDeviceName = Build.MODEL;
85         }
86     }
87 
88     @Override
getSummary()89     public CharSequence getSummary() {
90         return mDeviceName;
91     }
92 
93     @Override
getAvailabilityStatus()94     public int getAvailabilityStatus() {
95         return AVAILABLE;
96     }
97 
98     @Override
getPreferenceKey()99     public String getPreferenceKey() {
100         return PREF_KEY;
101     }
102 
103     @Override
onPreferenceChange(Preference preference, Object newValue)104     public boolean onPreferenceChange(Preference preference, Object newValue) {
105         mPendingDeviceName = (String) newValue;
106         if (mHost != null) {
107             mHost.showDeviceNameWarningDialog(mPendingDeviceName);
108         }
109         return true;
110     }
111 
112     @Override
isTextValid(String deviceName)113     public boolean isTextValid(String deviceName) {
114         // BluetoothNameDialogFragment describes BT name filter as a 248 bytes long cap.
115         // Given the restrictions presented by the SSID name filter (32 char), I don't believe it is
116         // possible to construct an SSID that is not a valid Bluetooth name.
117         return mWifiDeviceNameTextValidator.isTextValid(deviceName);
118     }
119 
setLocalBluetoothManager(LocalBluetoothManager localBluetoothManager)120     public void setLocalBluetoothManager(LocalBluetoothManager localBluetoothManager) {
121         mBluetoothManager = localBluetoothManager;
122     }
123 
confirmDeviceName()124     public void confirmDeviceName() {
125         if (mPendingDeviceName != null) {
126             setDeviceName(mPendingDeviceName);
127         }
128     }
129 
setHost(DeviceNamePreferenceHost host)130     public void setHost(DeviceNamePreferenceHost host) {
131         mHost = host;
132     }
133 
134     /**
135      * This method presumes that security/validity checks have already been passed.
136      */
setDeviceName(String deviceName)137     private void setDeviceName(String deviceName) {
138         mDeviceName = deviceName;
139         setSettingsGlobalDeviceName(deviceName);
140         setBluetoothDeviceName(deviceName);
141         setTetherSsidName(deviceName);
142         mPreference.setSummary(getSummary());
143     }
144 
setSettingsGlobalDeviceName(String deviceName)145     private void setSettingsGlobalDeviceName(String deviceName) {
146         Settings.Global.putString(mContext.getContentResolver(), Settings.Global.DEVICE_NAME,
147                 deviceName);
148     }
149 
setBluetoothDeviceName(String deviceName)150     private void setBluetoothDeviceName(String deviceName) {
151         // Bluetooth manager doesn't exist for certain devices.
152         if (mBluetoothManager == null) {
153             return;
154         }
155 
156         final LocalBluetoothAdapter localBluetoothAdapter = mBluetoothManager.getBluetoothAdapter();
157         if (localBluetoothAdapter != null) {
158             localBluetoothAdapter.setName(getFilteredBluetoothString(deviceName));
159         }
160     }
161 
162     /**
163      * Using a UTF8ByteLengthFilter, we can filter a string to be compliant with the Bluetooth spec.
164      * For more information, see {@link com.android.settings.bluetooth.BluetoothNameDialogFragment}.
165      */
getFilteredBluetoothString(final String deviceName)166     private static final String getFilteredBluetoothString(final String deviceName) {
167         CharSequence filteredSequence = new BluetoothLengthDeviceNameFilter().filter(deviceName, 0, deviceName.length(),
168                 new SpannedString(""),
169                 0, 0);
170         // null -> use the original
171         if (filteredSequence == null) {
172             return deviceName;
173         }
174         return filteredSequence.toString();
175     }
176 
setTetherSsidName(String deviceName)177     private void setTetherSsidName(String deviceName) {
178         final WifiConfiguration config = mWifiManager.getWifiApConfiguration();
179         config.SSID = deviceName;
180         // TODO: If tether is running, turn off the AP and restart it after setting config.
181         mWifiManager.setWifiApConfiguration(config);
182     }
183 
184     @Override
onCreate(Bundle savedInstanceState)185     public void onCreate(Bundle savedInstanceState) {
186         if (savedInstanceState != null) {
187             mPendingDeviceName = savedInstanceState.getString(KEY_PENDING_DEVICE_NAME, null);
188         }
189     }
190 
191     @Override
onSaveInstanceState(Bundle outState)192     public void onSaveInstanceState(Bundle outState) {
193         outState.putString(KEY_PENDING_DEVICE_NAME, mPendingDeviceName);
194     }
195 
196     public interface DeviceNamePreferenceHost {
showDeviceNameWarningDialog(String deviceName)197         void showDeviceNameWarningDialog(String deviceName);
198     }
199 }