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.systemui.statusbar.policy; 18 19 import android.app.ActivityManager; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.os.UserHandle; 25 import android.text.format.DateFormat; 26 import android.util.AttributeSet; 27 import android.widget.LinearLayout; 28 import android.widget.TextClock; 29 30 import com.android.systemui.R; 31 32 /** 33 * Container for a clock which has two separate views for the clock itself and AM/PM indicator. This 34 * is used to scale the clock independently of AM/PM. 35 */ 36 public class SplitClockView extends LinearLayout { 37 38 private TextClock mTimeView; 39 private TextClock mAmPmView; 40 41 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 42 @Override 43 public void onReceive(Context context, Intent intent) { 44 final String action = intent.getAction(); 45 if (Intent.ACTION_TIME_CHANGED.equals(action) 46 || Intent.ACTION_TIMEZONE_CHANGED.equals(action) 47 || Intent.ACTION_LOCALE_CHANGED.equals(action) 48 || Intent.ACTION_CONFIGURATION_CHANGED.equals(action) 49 || Intent.ACTION_USER_SWITCHED.equals(action)) { 50 updatePatterns(); 51 } 52 } 53 }; 54 SplitClockView(Context context, AttributeSet attrs)55 public SplitClockView(Context context, AttributeSet attrs) { 56 super(context, attrs); 57 } 58 59 @Override onFinishInflate()60 protected void onFinishInflate() { 61 super.onFinishInflate(); 62 mTimeView = (TextClock) findViewById(R.id.time_view); 63 mAmPmView = (TextClock) findViewById(R.id.am_pm_view); 64 mTimeView.setShowCurrentUserTime(true); 65 mAmPmView.setShowCurrentUserTime(true); 66 } 67 68 @Override onAttachedToWindow()69 protected void onAttachedToWindow() { 70 super.onAttachedToWindow(); 71 72 IntentFilter filter = new IntentFilter(); 73 filter.addAction(Intent.ACTION_TIME_CHANGED); 74 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 75 filter.addAction(Intent.ACTION_LOCALE_CHANGED); 76 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 77 filter.addAction(Intent.ACTION_USER_SWITCHED); 78 getContext().registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter, null, null); 79 80 updatePatterns(); 81 } 82 83 @Override onDetachedFromWindow()84 protected void onDetachedFromWindow() { 85 super.onDetachedFromWindow(); 86 getContext().unregisterReceiver(mIntentReceiver); 87 } 88 updatePatterns()89 private void updatePatterns() { 90 String formatString = DateFormat.getTimeFormatString(getContext(), 91 ActivityManager.getCurrentUser()); 92 int index = getAmPmPartEndIndex(formatString); 93 String timeString; 94 String amPmString; 95 if (index == -1) { 96 timeString = formatString; 97 amPmString = ""; 98 } else { 99 timeString = formatString.substring(0, index); 100 amPmString = formatString.substring(index); 101 } 102 mTimeView.setFormat12Hour(timeString); 103 mTimeView.setFormat24Hour(timeString); 104 mTimeView.setContentDescriptionFormat12Hour(formatString); 105 mTimeView.setContentDescriptionFormat24Hour(formatString); 106 mAmPmView.setFormat12Hour(amPmString); 107 mAmPmView.setFormat24Hour(amPmString); 108 } 109 110 /** 111 * @return the index where the AM/PM part starts at the end in {@code formatString} including 112 * leading white spaces or {@code -1} if no AM/PM part is found or {@code formatString} 113 * doesn't end with AM/PM part 114 */ getAmPmPartEndIndex(String formatString)115 private static int getAmPmPartEndIndex(String formatString) { 116 boolean hasAmPm = false; 117 int length = formatString.length(); 118 for (int i = length - 1; i >= 0; i--) { 119 char c = formatString.charAt(i); 120 boolean isAmPm = c == 'a'; 121 boolean isWhitespace = Character.isWhitespace(c); 122 if (isAmPm) { 123 hasAmPm = true; 124 } 125 if (isAmPm || isWhitespace) { 126 continue; 127 } 128 if (i == length - 1) { 129 130 // First character was not AM/PM and not whitespace, so it's not ending with AM/PM. 131 return -1; 132 } else { 133 134 // If we have AM/PM at all, return last index, or -1 to indicate that it's not 135 // ending with AM/PM. 136 return hasAmPm ? i + 1 : -1; 137 } 138 } 139 140 // Only AM/PM and whitespaces? The whole string is AM/PM. Else: Only whitespaces in the 141 // string. 142 return hasAmPm ? 0 : -1; 143 } 144 145 } 146