DisplaySettings.java revision d79934731c8d33f6fc63b21c120b9ffba5d06f54
1992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani/* 2992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * Copyright (C) 2010 The Android Open Source Project 3992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * 4992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * Licensed under the Apache License, Version 2.0 (the "License"); 5992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * you may not use this file except in compliance with the License. 6992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * You may obtain a copy of the License at 7992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * 8992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * http://www.apache.org/licenses/LICENSE-2.0 9992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * 10992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * Unless required by applicable law or agreed to in writing, software 11992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * distributed under the License is distributed on an "AS IS" BASIS, 12992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * See the License for the specific language governing permissions and 14992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani * limitations under the License. 15992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani */ 16992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 17992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasanipackage com.android.settings; 18992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 19992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; 20992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 21d90b5a84d8261a30db573de5a722722d6a37391eJim Millerimport android.app.admin.DevicePolicyManager; 22992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.content.ContentResolver; 23992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.content.Context; 24992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.os.Bundle; 25992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.os.RemoteException; 26992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.os.ServiceManager; 27992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.preference.CheckBoxPreference; 28992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.preference.ListPreference; 29992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.preference.Preference; 30992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.preference.PreferenceScreen; 31992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.provider.Settings; 32992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.util.Log; 33992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasaniimport android.view.IWindowManager; 34992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 35d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasaniimport java.util.ArrayList; 36d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani 37d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasanipublic class DisplaySettings extends SettingsPreferenceFragment implements 38992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani Preference.OnPreferenceChangeListener { 39992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private static final String TAG = "DisplaySettings"; 40992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 41992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani /** If there is no setting in the provider, use this. */ 42992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000; 43992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 44992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private static final String KEY_SCREEN_TIMEOUT = "screen_timeout"; 45992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private static final String KEY_ANIMATIONS = "animations"; 46992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private static final String KEY_ACCELEROMETER = "accelerometer"; 47992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 48992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private ListPreference mAnimations; 49992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private CheckBoxPreference mAccelerometer; 50992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private float[] mAnimationScales; 51992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 52992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private IWindowManager mWindowManager; 53992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 54992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani @Override 55d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani public void onCreate(Bundle savedInstanceState) { 56992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani super.onCreate(savedInstanceState); 57d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani ContentResolver resolver = getActivity().getContentResolver(); 58992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 59992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 60992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani addPreferencesFromResource(R.xml.display_settings); 61992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 62992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAnimations = (ListPreference) findPreference(KEY_ANIMATIONS); 63992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAnimations.setOnPreferenceChangeListener(this); 64992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAccelerometer = (CheckBoxPreference) findPreference(KEY_ACCELEROMETER); 65992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAccelerometer.setPersistent(false); 66992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 67992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani ListPreference screenTimeoutPreference = 68992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani (ListPreference) findPreference(KEY_SCREEN_TIMEOUT); 69992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani screenTimeoutPreference.setValue(String.valueOf(Settings.System.getInt( 70992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani resolver, SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE))); 71992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani screenTimeoutPreference.setOnPreferenceChangeListener(this); 72d90b5a84d8261a30db573de5a722722d6a37391eJim Miller disableUnusableTimeouts(screenTimeoutPreference); 73d90b5a84d8261a30db573de5a722722d6a37391eJim Miller } 74992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 75d90b5a84d8261a30db573de5a722722d6a37391eJim Miller private void disableUnusableTimeouts(ListPreference screenTimeoutPreference) { 76fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller final DevicePolicyManager dpm = 77d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani (DevicePolicyManager) getActivity().getSystemService( 78d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani Context.DEVICE_POLICY_SERVICE); 79fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller final long maxTimeout = dpm != null ? dpm.getMaximumTimeToLock(null) : 0; 80d90b5a84d8261a30db573de5a722722d6a37391eJim Miller if (maxTimeout == 0) { 81d90b5a84d8261a30db573de5a722722d6a37391eJim Miller return; // policy not enforced 82d90b5a84d8261a30db573de5a722722d6a37391eJim Miller } 83d90b5a84d8261a30db573de5a722722d6a37391eJim Miller final CharSequence[] entries = screenTimeoutPreference.getEntries(); 84d90b5a84d8261a30db573de5a722722d6a37391eJim Miller final CharSequence[] values = screenTimeoutPreference.getEntryValues(); 85d90b5a84d8261a30db573de5a722722d6a37391eJim Miller ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>(); 86d90b5a84d8261a30db573de5a722722d6a37391eJim Miller ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>(); 87d90b5a84d8261a30db573de5a722722d6a37391eJim Miller for (int i = 0; i < values.length; i++) { 88d90b5a84d8261a30db573de5a722722d6a37391eJim Miller long timeout = Long.valueOf(values[i].toString()); 89d90b5a84d8261a30db573de5a722722d6a37391eJim Miller if (timeout <= maxTimeout) { 90d90b5a84d8261a30db573de5a722722d6a37391eJim Miller revisedEntries.add(entries[i]); 91d90b5a84d8261a30db573de5a722722d6a37391eJim Miller revisedValues.add(values[i]); 92d90b5a84d8261a30db573de5a722722d6a37391eJim Miller } 93d90b5a84d8261a30db573de5a722722d6a37391eJim Miller } 94d90b5a84d8261a30db573de5a722722d6a37391eJim Miller if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) { 95d90b5a84d8261a30db573de5a722722d6a37391eJim Miller screenTimeoutPreference.setEntries( 96d90b5a84d8261a30db573de5a722722d6a37391eJim Miller revisedEntries.toArray(new CharSequence[revisedEntries.size()])); 97d90b5a84d8261a30db573de5a722722d6a37391eJim Miller screenTimeoutPreference.setEntryValues( 98d90b5a84d8261a30db573de5a722722d6a37391eJim Miller revisedValues.toArray(new CharSequence[revisedValues.size()])); 99fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller final int userPreference = Integer.valueOf(screenTimeoutPreference.getValue()); 100fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller if (userPreference <= maxTimeout) { 101fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller screenTimeoutPreference.setValue(String.valueOf(userPreference)); 102fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller } else { 103fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller // There will be no highlighted selection since nothing in the list matches 104fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller // maxTimeout. The user can still select anything less than maxTimeout. 105fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller // TODO: maybe append maxTimeout to the list and mark selected. 106fc5a02225e8bca21f07543f55e1b51a33670c501Jim Miller } 107d90b5a84d8261a30db573de5a722722d6a37391eJim Miller } 108d90b5a84d8261a30db573de5a722722d6a37391eJim Miller screenTimeoutPreference.setEnabled(revisedEntries.size() > 0); 109992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 110992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 111992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani @Override 112d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani public void onResume() { 113992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani super.onResume(); 114992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 115992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani updateState(true); 116992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 117992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 118992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private void updateState(boolean force) { 119992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani int animations = 0; 120992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani try { 121992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAnimationScales = mWindowManager.getAnimationScales(); 122992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } catch (RemoteException e) { 123992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 124992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (mAnimationScales != null) { 125992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (mAnimationScales.length >= 1) { 126992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani animations = ((int)(mAnimationScales[0]+.5f)) % 10; 127992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 128992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (mAnimationScales.length >= 2) { 129992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani animations += (((int)(mAnimationScales[1]+.5f)) & 0x7) * 10; 130992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 131992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 132992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani int idx = 0; 133992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani int best = 0; 134992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani CharSequence[] aents = mAnimations.getEntryValues(); 135992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani for (int i=0; i<aents.length; i++) { 136992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani int val = Integer.parseInt(aents[i].toString()); 137992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (val <= animations && val > best) { 138992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani best = val; 139992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani idx = i; 140992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 141992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 142992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAnimations.setValueIndex(idx); 143992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani updateAnimationsSummary(mAnimations.getValue()); 144992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAccelerometer.setChecked(Settings.System.getInt( 145992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani getContentResolver(), 146992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani Settings.System.ACCELEROMETER_ROTATION, 0) != 0); 147992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 148992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 149992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani private void updateAnimationsSummary(Object value) { 150992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani CharSequence[] summaries = getResources().getTextArray(R.array.animations_summaries); 151992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani CharSequence[] values = mAnimations.getEntryValues(); 152992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani for (int i=0; i<values.length; i++) { 153992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani //Log.i("foo", "Comparing entry "+ values[i] + " to current " 154992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani // + mAnimations.getValue()); 155992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (values[i].equals(value)) { 156992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAnimations.setSummary(summaries[i]); 157992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani break; 158992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 159992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 160992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 161992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 162992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani @Override 163992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 164992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (preference == mAccelerometer) { 165992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani Settings.System.putInt(getContentResolver(), 166992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani Settings.System.ACCELEROMETER_ROTATION, 167992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAccelerometer.isChecked() ? 1 : 0); 168992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 169992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani return true; 170992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 171992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 172992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani public boolean onPreferenceChange(Preference preference, Object objValue) { 173992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani final String key = preference.getKey(); 174992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (KEY_ANIMATIONS.equals(key)) { 175992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani try { 176992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani int value = Integer.parseInt((String) objValue); 177992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (mAnimationScales.length >= 1) { 178992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAnimationScales[0] = value%10; 179992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 180992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (mAnimationScales.length >= 2) { 181992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mAnimationScales[1] = (value/10)%10; 182992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 183992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani try { 184992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani mWindowManager.setAnimationScales(mAnimationScales); 185992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } catch (RemoteException e) { 186992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 187992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani updateAnimationsSummary(objValue); 188992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } catch (NumberFormatException e) { 189992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani Log.e(TAG, "could not persist animation setting", e); 190992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 191992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 192992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 193992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani if (KEY_SCREEN_TIMEOUT.equals(key)) { 194992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani int value = Integer.parseInt((String) objValue); 195992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani try { 196992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani Settings.System.putInt(getContentResolver(), 197992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani SCREEN_OFF_TIMEOUT, value); 198992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } catch (NumberFormatException e) { 199992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani Log.e(TAG, "could not persist screen timeout setting", e); 200992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 201992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 202992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani 203992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani return true; 204992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani } 205992f10240d0bfd78bb99855fe23ec7a1b61a2551Amith Yamasani} 206