Home | History | Annotate | Download | only in system
      1 /*
      2  * Copyright (C) 2014 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.tv.settings.system;
     18 
     19 import android.app.AlarmManager;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.content.res.Resources;
     25 import android.os.Bundle;
     26 import android.provider.Settings;
     27 import android.provider.Settings.SettingNotFoundException;
     28 import android.text.format.DateFormat;
     29 
     30 import com.android.settingslib.datetime.ZoneGetter;
     31 import com.android.tv.settings.R;
     32 import com.android.tv.settings.dialog.Layout;
     33 import com.android.tv.settings.dialog.SettingsLayoutActivity;
     34 import com.android.tv.settings.util.SettingsHelper;
     35 
     36 import java.util.Calendar;
     37 import java.util.Collections;
     38 import java.util.Comparator;
     39 import java.util.Date;
     40 import java.util.List;
     41 import java.util.Map;
     42 import java.util.TimeZone;
     43 
     44 public class DateTimeActivity extends SettingsLayoutActivity {
     45 
     46     private static final String TAG = "DateTimeActivity";
     47 
     48     private static final String HOURS_12 = "12";
     49     private static final String HOURS_24 = "24";
     50 
     51     private static final int ACTION_AUTO_TIME_ON = 0;
     52     private static final int ACTION_AUTO_TIME_OFF = 1;
     53     private static final int ACTION_24HOUR_FORMAT_ON = 3;
     54     private static final int ACTION_24HOUR_FORMAT_OFF = 4;
     55     private static final int ACTION_SET_TIMEZONE_BASE = 1<<10;
     56 
     57 
     58     private Calendar mDummyDate;
     59     private boolean mIsResumed;
     60 
     61     private String mNowDate;
     62     private String mNowTime;
     63 
     64     private SettingsHelper mHelper;
     65 
     66     private final BroadcastReceiver mTimeUpdateIntentReceiver = new BroadcastReceiver() {
     67         @Override
     68         public void onReceive(Context context, Intent intent) {
     69             if (mIsResumed) {
     70                 updateTimeAndDateStrings();
     71             }
     72         }
     73     };
     74 
     75     private final Layout.StringGetter mTimeStringGetter = new Layout.StringGetter() {
     76         @Override
     77         public String get() {
     78             return mNowTime;
     79         }
     80     };
     81 
     82     private final Layout.StringGetter mDateStringGetter = new Layout.StringGetter() {
     83         @Override
     84         public String get() {
     85             return mNowDate;
     86         }
     87     };
     88 
     89     private final Layout.StringGetter mTimezoneStringGetter = new Layout.StringGetter() {
     90         @Override
     91         public String get() {
     92             final Calendar now = Calendar.getInstance();
     93             TimeZone tz = now.getTimeZone();
     94 
     95             Date date = new Date();
     96             return getString(R.string.desc_set_time_zone,
     97                     formatOffset(tz.getOffset(date.getTime())),
     98                     tz.getDisplayName(tz.inDaylightTime(date), TimeZone.LONG));
     99         }
    100     };
    101 
    102     private final Layout.StringGetter mTimeFormatStringGetter = new Layout.StringGetter() {
    103         @Override
    104         public String get() {
    105             String status = mHelper.getStatusStringFromBoolean(isTimeFormat24h());
    106             return getString(R.string.desc_set_time_format, status,
    107                     DateFormat.getTimeFormat(DateTimeActivity.this).format(mDummyDate.getTime()));
    108         }
    109     };
    110 
    111     private final Layout.LayoutGetter mSetDateLayoutGetter = new Layout.LayoutGetter() {
    112         @Override
    113         public Layout get() {
    114             final Resources res = getResources();
    115             return new Layout()
    116                     .add(new Layout.Header.Builder(res)
    117                             .title(R.string.system_date)
    118                             .description(mDateStringGetter)
    119                             .enabled(!getAutoState(Settings.Global.AUTO_TIME))
    120                             .build()
    121                             .add(new Layout.Action.Builder(res,
    122                                     SetDateTimeActivity.getSetDateIntent(DateTimeActivity.this))
    123                                     .title(R.string.system_set_date)
    124                                     .description(mDateStringGetter)
    125                                     .build()));
    126         }
    127     };
    128 
    129     private final Layout.LayoutGetter mSetTimeLayoutGetter = new Layout.LayoutGetter() {
    130         @Override
    131         public Layout get() {
    132             final Resources res = getResources();
    133             return new Layout()
    134                     .add(new Layout.Action.Builder(res,
    135                             SetDateTimeActivity.getSetTimeIntent(DateTimeActivity.this))
    136                             .title(R.string.system_set_time)
    137                             .description(mTimeStringGetter)
    138                             .enabled(!getAutoState(Settings.Global.AUTO_TIME))
    139                             .build());
    140 
    141         }
    142     };
    143 
    144     private Layout.SelectionGroup mAutoDateTimeSelector;
    145     private Layout.SelectionGroup mTimezoneSelector;
    146     private Layout.SelectionGroup mTimeFormatSelector;
    147 
    148     private List<Map<String, Object>> mTimeZones;
    149 
    150     @Override
    151     public void onCreate(Bundle savedInstanceState) {
    152         mDummyDate = Calendar.getInstance();
    153 
    154         mHelper = new SettingsHelper(getApplicationContext());
    155 
    156         // Auto date time
    157         mAutoDateTimeSelector = new Layout.SelectionGroup.Builder(2)
    158                 .add(getString(R.string.action_on_description), null, ACTION_AUTO_TIME_ON)
    159                 .add(getString(R.string.action_off_description), null, ACTION_AUTO_TIME_OFF)
    160                 .build();
    161         mAutoDateTimeSelector.setSelected(getAutoState(Settings.Global.AUTO_TIME) ?
    162                 ACTION_AUTO_TIME_ON : ACTION_AUTO_TIME_OFF);
    163 
    164         // Time zone
    165         mTimeZones = ZoneGetter.getZonesList(this);
    166         // Sort the Time Zones list in ascending offset order
    167         Collections.sort(mTimeZones, new MyComparator(ZoneGetter.KEY_OFFSET));
    168         final TimeZone currentTz = TimeZone.getDefault();
    169 
    170         final Layout.SelectionGroup.Builder tzBuilder =
    171                 new Layout.SelectionGroup.Builder(mTimeZones.size());
    172 
    173         int i = ACTION_SET_TIMEZONE_BASE;
    174         int currentTzActionId = -1;
    175         for (final Map<String, Object> tz : mTimeZones) {
    176             if (currentTz.getID().equals(tz.get(ZoneGetter.KEY_ID))) {
    177                 currentTzActionId = i;
    178             }
    179             tzBuilder.add((String) tz.get(ZoneGetter.KEY_DISPLAYNAME),
    180                     formatOffset((Integer) tz.get(ZoneGetter.KEY_OFFSET)), i);
    181             i++;
    182         }
    183 
    184         mTimezoneSelector = tzBuilder.build();
    185         mTimezoneSelector.setSelected(currentTzActionId);
    186 
    187         // Time Format
    188         mTimeFormatSelector = new Layout.SelectionGroup.Builder(2)
    189                 .add(getString(R.string.settings_on), null, ACTION_24HOUR_FORMAT_ON)
    190                 .add(getString(R.string.settings_off), null, ACTION_24HOUR_FORMAT_OFF)
    191                 .build();
    192 
    193         setSampleDate();
    194 
    195         updateTimeAndDateStrings();
    196 
    197         super.onCreate(savedInstanceState);
    198     }
    199 
    200     @Override
    201     protected void onResume() {
    202         super.onResume();
    203         mIsResumed = true;
    204 
    205         final IntentFilter filter = new IntentFilter();
    206         filter.addAction(Intent.ACTION_TIME_TICK);
    207         filter.addAction(Intent.ACTION_TIME_CHANGED);
    208         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
    209         filter.addAction(Intent.ACTION_DATE_CHANGED);
    210 
    211         registerReceiver(mTimeUpdateIntentReceiver, filter);
    212 
    213         updateTimeAndDateStrings();
    214     }
    215 
    216     @Override
    217     protected void onPause() {
    218         super.onPause();
    219         mIsResumed = false;
    220         unregisterReceiver(mTimeUpdateIntentReceiver);
    221     }
    222 
    223     @Override
    224     public Layout createLayout() {
    225         final Resources res = getResources();
    226         return new Layout().breadcrumb(getString(R.string.header_category_preferences))
    227                 .add(new Layout.Header.Builder(res)
    228                         .icon(R.drawable.ic_settings_datetime)
    229                         .title(R.string.system_date_time)
    230                         .build()
    231                         .add(new Layout.Header.Builder(res)
    232                                 .title(R.string.system_auto_date_time)
    233                                 .description(mAutoDateTimeSelector)
    234                                 .build()
    235                                 .add(mAutoDateTimeSelector))
    236                         .add(mSetDateLayoutGetter)
    237                         .add(new Layout.Header.Builder(res)
    238                                 .title(R.string.system_time)
    239                                 .description(mTimeStringGetter)
    240                                 .build()
    241                                 .add(mSetTimeLayoutGetter)
    242                                 .add(new Layout.Header.Builder(res)
    243                                         .title(R.string.system_set_time_zone)
    244                                         .description(mTimezoneStringGetter)
    245                                         .build()
    246                                         .add(mTimezoneSelector))
    247                                 .add(new Layout.Header.Builder(res)
    248                                         .title(R.string.system_set_time_format)
    249                                         .description(mTimeFormatStringGetter)
    250                                         .build()
    251                                         .add(mTimeFormatSelector))));
    252     }
    253 
    254     private void setSampleDate() {
    255         Calendar now = Calendar.getInstance();
    256         mDummyDate.setTimeZone(now.getTimeZone());
    257         // We use December 31st because it's unambiguous when demonstrating the date format.
    258         // We use 15:14 so we can demonstrate the 12/24 hour options.
    259         mDummyDate.set(now.get(Calendar.YEAR), 11, 31, 15, 14, 0);
    260     }
    261 
    262     private boolean getAutoState(String name) {
    263         try {
    264             return Settings.Global.getInt(getContentResolver(), name) > 0;
    265         } catch (SettingNotFoundException snfe) {
    266             return false;
    267         }
    268     }
    269 
    270 
    271     private boolean isTimeFormat24h() {
    272         return DateFormat.is24HourFormat(this);
    273     }
    274 
    275     private void setTime24Hour(boolean is24Hour) {
    276         Settings.System.putString(getContentResolver(),
    277                 Settings.System.TIME_12_24,
    278                 is24Hour ? HOURS_24 : HOURS_12);
    279         updateTimeAndDateStrings();
    280     }
    281 
    282     private void setAutoDateTime(boolean on) {
    283         Settings.Global.putInt(getContentResolver(), Settings.Global.AUTO_TIME, on ? 1 : 0);
    284     }
    285 
    286     // Updates the member strings to reflect the current date and time.
    287     private void updateTimeAndDateStrings() {
    288         final Calendar now = Calendar.getInstance();
    289         java.text.DateFormat dateFormat = DateFormat.getDateFormat(this);
    290         mNowDate = dateFormat.format(now.getTime());
    291         java.text.DateFormat timeFormat = DateFormat.getTimeFormat(this);
    292         mNowTime = timeFormat.format(now.getTime());
    293 
    294         mDateStringGetter.refreshView();
    295         mTimeStringGetter.refreshView();
    296     }
    297 
    298     @Override
    299     public void onActionClicked(Layout.Action action) {
    300         final int actionId = action.getId();
    301         switch (actionId) {
    302             case Layout.Action.ACTION_INTENT:
    303                 startActivity(action.getIntent());
    304                 break;
    305             case ACTION_AUTO_TIME_ON:
    306                 setAutoDateTime(true);
    307                 mSetDateLayoutGetter.refreshView();
    308                 mSetTimeLayoutGetter.refreshView();
    309                 break;
    310             case ACTION_AUTO_TIME_OFF:
    311                 setAutoDateTime(false);
    312                 mSetDateLayoutGetter.refreshView();
    313                 mSetTimeLayoutGetter.refreshView();
    314                 break;
    315             case ACTION_24HOUR_FORMAT_ON:
    316                 setTime24Hour(true);
    317                 break;
    318             case ACTION_24HOUR_FORMAT_OFF:
    319                 setTime24Hour(false);
    320                 break;
    321             default:
    322                 if ((actionId & ACTION_SET_TIMEZONE_BASE) != 0) {
    323                     setTimeZone((String) mTimeZones.get(actionId - ACTION_SET_TIMEZONE_BASE)
    324                             .get(ZoneGetter.KEY_ID));
    325                 }
    326                 break;
    327         }
    328     }
    329 
    330     /**
    331      * Formats the provided timezone offset into a string of the form GMT+XX:XX
    332      */
    333     private static String formatOffset(long offset) {
    334         long off = offset / 1000 / 60;
    335         final StringBuilder sb = new StringBuilder();
    336 
    337         sb.append("GMT");
    338         if (off < 0) {
    339             sb.append('-');
    340             off = -off;
    341         } else {
    342             sb.append('+');
    343         }
    344 
    345         int hours = (int) (off / 60);
    346         int minutes = (int) (off % 60);
    347 
    348         sb.append((char) ('0' + hours / 10));
    349         sb.append((char) ('0' + hours % 10));
    350 
    351         sb.append(':');
    352 
    353         sb.append((char) ('0' + minutes / 10));
    354         sb.append((char) ('0' + minutes % 10));
    355 
    356         return sb.toString();
    357     }
    358 
    359     private void setTimeZone(String tzId) {
    360         // Update the system timezone value
    361         final AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    362         alarm.setTimeZone(tzId);
    363 
    364         setSampleDate();
    365     }
    366 
    367     private static class MyComparator implements Comparator<Map<?, ?>> {
    368         private String mSortingKey;
    369 
    370         public MyComparator(String sortingKey) {
    371             mSortingKey = sortingKey;
    372         }
    373 
    374         public void setSortingKey(String sortingKey) {
    375             mSortingKey = sortingKey;
    376         }
    377 
    378         public int compare(Map<?, ?> map1, Map<?, ?> map2) {
    379             Object value1 = map1.get(mSortingKey);
    380             Object value2 = map2.get(mSortingKey);
    381 
    382             /*
    383              * This should never happen, but just in-case, put non-comparable
    384              * items at the end.
    385              */
    386             if (!isComparable(value1)) {
    387                 return isComparable(value2) ? 1 : 0;
    388             } else if (!isComparable(value2)) {
    389                 return -1;
    390             }
    391 
    392             return ((Comparable) value1).compareTo(value2);
    393         }
    394 
    395         private boolean isComparable(Object value) {
    396             return (value != null) && (value instanceof Comparable);
    397         }
    398     }
    399 
    400 }
    401