1329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi/* 2329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * Copyright (C) 2014 The Android Open Source Project 3329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * 4329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 5329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * you may not use this file except in compliance with the License. 6329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * You may obtain a copy of the License at 7329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * 8329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 9329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * 10329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * Unless required by applicable law or agreed to in writing, software 11329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 12329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * See the License for the specific language governing permissions and 14329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * limitations under the License 15329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi */ 16329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 17329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggipackage com.android.systemui.statusbar.policy; 18329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 199c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinekimport android.app.ActivityManager; 20329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggiimport android.content.BroadcastReceiver; 21329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggiimport android.content.Context; 22329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggiimport android.content.Intent; 23329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggiimport android.content.IntentFilter; 249c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinekimport android.os.UserHandle; 25329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggiimport android.text.format.DateFormat; 26329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggiimport android.util.AttributeSet; 27329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggiimport android.widget.LinearLayout; 28329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggiimport android.widget.TextClock; 29329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 30329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggiimport com.android.systemui.R; 31329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 32329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi/** 33329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * Container for a clock which has two separate views for the clock itself and AM/PM indicator. This 34329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * is used to scale the clock independently of AM/PM. 35329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi */ 36329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggipublic class SplitClockView extends LinearLayout { 37329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 38329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi private TextClock mTimeView; 39329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi private TextClock mAmPmView; 40329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 41329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 42329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi @Override 43329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi public void onReceive(Context context, Intent intent) { 44329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi final String action = intent.getAction(); 45329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi if (Intent.ACTION_TIME_CHANGED.equals(action) 46329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi || Intent.ACTION_TIMEZONE_CHANGED.equals(action) 479c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek || Intent.ACTION_LOCALE_CHANGED.equals(action) 489c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek || Intent.ACTION_CONFIGURATION_CHANGED.equals(action) 499c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek || Intent.ACTION_USER_SWITCHED.equals(action)) { 50329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi updatePatterns(); 51329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 52329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 53329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi }; 54329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 55329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi public SplitClockView(Context context, AttributeSet attrs) { 56329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi super(context, attrs); 57329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 58329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 59329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi @Override 60329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi protected void onFinishInflate() { 61329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi super.onFinishInflate(); 62329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi mTimeView = (TextClock) findViewById(R.id.time_view); 63329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi mAmPmView = (TextClock) findViewById(R.id.am_pm_view); 649c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek mTimeView.setShowCurrentUserTime(true); 659c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek mAmPmView.setShowCurrentUserTime(true); 66329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 67329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 68329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi @Override 69329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi protected void onAttachedToWindow() { 70329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi super.onAttachedToWindow(); 71329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 72329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi IntentFilter filter = new IntentFilter(); 73329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi filter.addAction(Intent.ACTION_TIME_CHANGED); 74329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 75329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi filter.addAction(Intent.ACTION_LOCALE_CHANGED); 769c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 779c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek filter.addAction(Intent.ACTION_USER_SWITCHED); 789c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek getContext().registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter, null, null); 79329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 80329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi updatePatterns(); 81329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 82329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 83329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi @Override 84329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi protected void onDetachedFromWindow() { 85329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi super.onDetachedFromWindow(); 86329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi getContext().unregisterReceiver(mIntentReceiver); 87329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 88329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 89329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi private void updatePatterns() { 909c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek String formatString = DateFormat.getTimeFormatString(getContext(), 919c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek ActivityManager.getCurrentUser()); 92329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi int index = getAmPmPartEndIndex(formatString); 93329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi String timeString; 94329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi String amPmString; 95329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi if (index == -1) { 96329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi timeString = formatString; 97329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi amPmString = ""; 98329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } else { 99329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi timeString = formatString.substring(0, index); 100329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi amPmString = formatString.substring(index); 101329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 102329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi mTimeView.setFormat12Hour(timeString); 103329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi mTimeView.setFormat24Hour(timeString); 104329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi mAmPmView.setFormat12Hour(amPmString); 105329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi mAmPmView.setFormat24Hour(amPmString); 106329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 107329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 108329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi /** 109329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * @return the index where the AM/PM part starts at the end in {@code formatString} including 110329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * leading white spaces or {@code -1} if no AM/PM part is found or {@code formatString} 111329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi * doesn't end with AM/PM part 112329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi */ 113329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi private static int getAmPmPartEndIndex(String formatString) { 114329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi boolean hasAmPm = false; 115329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi int length = formatString.length(); 116329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi for (int i = length - 1; i >= 0; i--) { 117329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi char c = formatString.charAt(i); 118329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi boolean isAmPm = c == 'a'; 119329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi boolean isWhitespace = Character.isWhitespace(c); 120329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi if (isAmPm) { 121329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi hasAmPm = true; 122329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 123329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi if (isAmPm || isWhitespace) { 124329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi continue; 125329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 126329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi if (i == length - 1) { 127329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 128329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi // First character was not AM/PM and not whitespace, so it's not ending with AM/PM. 129329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi return -1; 130329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } else { 131329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 132329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi // If we have AM/PM at all, return last index, or -1 to indicate that it's not 133329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi // ending with AM/PM. 134329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi return hasAmPm ? i + 1 : -1; 135329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 136329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 137329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 138329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi // Only AM/PM and whitespaces? The whole string is AM/PM. Else: Only whitespaces in the 139329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi // string. 140329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi return hasAmPm ? 0 : -1; 141329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi } 142329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi 143329fa24048ffc8a35566bbacb891ac144be85b1cJorim Jaggi} 144