1624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey/* 2624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Copyright (C) 2009 The Android Open Source Project 3624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * 4624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * you may not use this file except in compliance with the License. 6624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * You may obtain a copy of the License at 7624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * 8624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * 10624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * See the License for the specific language governing permissions and 14624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * limitations under the License. 15624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey */ 16624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 17624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeypackage com.android.contacts.util; 18624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 19624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.content.Context; 20624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.content.pm.PackageManager; 21624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.database.Cursor; 22624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.graphics.drawable.Drawable; 23624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.provider.ContactsContract.Data; 24624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.text.TextUtils; 25624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.text.format.DateUtils; 26624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 279fcf4b162328ccc35a473a1b3c11f4d02ab06bcaEric Fischerimport com.android.contacts.R; 289fcf4b162328ccc35a473a1b3c11f4d02ab06bcaEric Fischer 29624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey/** 30624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Storage for a social status update. Holds a single update, but can use 31624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * {@link #possibleUpdate(Cursor)} to consider updating when a better status 32624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * exists. Statuses with timestamps, or with newer timestamps win. 33624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey */ 34624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeypublic class DataStatus { 35624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private int mPresence = -1; 36624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private String mStatus = null; 37624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private long mTimestamp = -1; 38624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 39624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private String mResPackage = null; 40624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private int mIconRes = -1; 41624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private int mLabelRes = -1; 42624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 43624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey public DataStatus() { 44624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 45624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 46624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey public DataStatus(Cursor cursor) { 47624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey // When creating from cursor row, fill normally 48624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey fromCursor(cursor); 49624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 50624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 51624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey /** 52624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Attempt updating this {@link DataStatus} based on values at the 53624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * current row of the given {@link Cursor}. 54624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey */ 55624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey public void possibleUpdate(Cursor cursor) { 56624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final boolean hasStatus = !isNull(cursor, Data.STATUS); 57624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final boolean hasTimestamp = !isNull(cursor, Data.STATUS_TIMESTAMP); 58624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 59624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey // Bail early when not valid status, or when previous status was 60624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey // found and we can't compare this one. 61624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey if (!hasStatus) return; 62624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey if (isValid() && !hasTimestamp) return; 63624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 64624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey if (hasTimestamp) { 65624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey // Compare timestamps and bail if older status 66624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final long newTimestamp = getLong(cursor, Data.STATUS_TIMESTAMP, -1); 67624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey if (newTimestamp < mTimestamp) return; 68624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 69624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey mTimestamp = newTimestamp; 70624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 71624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 72624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey // Fill in remaining details from cursor 73624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey fromCursor(cursor); 74624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 75624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 76624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private void fromCursor(Cursor cursor) { 77624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey mPresence = getInt(cursor, Data.PRESENCE, -1); 78624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey mStatus = getString(cursor, Data.STATUS); 79624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey mTimestamp = getLong(cursor, Data.STATUS_TIMESTAMP, -1); 80624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey mResPackage = getString(cursor, Data.STATUS_RES_PACKAGE); 81624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey mIconRes = getInt(cursor, Data.STATUS_ICON, -1); 82624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey mLabelRes = getInt(cursor, Data.STATUS_LABEL, -1); 83624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 84624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 85624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey public boolean isValid() { 86624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return !TextUtils.isEmpty(mStatus); 87624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 88624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 89624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey public int getPresence() { 90624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return mPresence; 91624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 92624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 93624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey public CharSequence getStatus() { 94624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return mStatus; 95624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 96624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 977f10d5670893aad216a90adba12b1faeec9b42a7Dmitri Plotnikov public long getTimestamp() { 987f10d5670893aad216a90adba12b1faeec9b42a7Dmitri Plotnikov return mTimestamp; 997f10d5670893aad216a90adba12b1faeec9b42a7Dmitri Plotnikov } 1007f10d5670893aad216a90adba12b1faeec9b42a7Dmitri Plotnikov 101624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey /** 102624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Build any timestamp and label into a single string. 103624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey */ 104624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey public CharSequence getTimestampLabel(Context context) { 105624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final PackageManager pm = context.getPackageManager(); 106624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 107b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey // Use local package for resources when none requested 108b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey if (mResPackage == null) mResPackage = context.getPackageName(); 109b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey 110624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final boolean validTimestamp = mTimestamp > 0; 111624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final boolean validLabel = mResPackage != null && mLabelRes != -1; 112624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 113624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final CharSequence timeClause = validTimestamp ? DateUtils.getRelativeTimeSpanString( 114624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey mTimestamp, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, 115624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey DateUtils.FORMAT_ABBREV_RELATIVE) : null; 116624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final CharSequence labelClause = validLabel ? pm.getText(mResPackage, mLabelRes, 117624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey null) : null; 118624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 119624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey if (validTimestamp && validLabel) { 120624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return context.getString( 1219fcf4b162328ccc35a473a1b3c11f4d02ab06bcaEric Fischer R.string.contact_status_update_attribution_with_date, 122624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey timeClause, labelClause); 123624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } else if (validLabel) { 124624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return context.getString( 1259fcf4b162328ccc35a473a1b3c11f4d02ab06bcaEric Fischer R.string.contact_status_update_attribution, 126624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey labelClause); 127624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } else if (validTimestamp) { 128624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return timeClause; 129624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } else { 130624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return null; 131624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 132624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 133624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 134624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey public Drawable getIcon(Context context) { 135624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final PackageManager pm = context.getPackageManager(); 136b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey 137b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey // Use local package for resources when none requested 138b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey if (mResPackage == null) mResPackage = context.getPackageName(); 139b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey 140624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final boolean validIcon = mResPackage != null && mIconRes != -1; 141624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return validIcon ? pm.getDrawable(mResPackage, mIconRes, null) : null; 142624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 143624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 144624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private static String getString(Cursor cursor, String columnName) { 145624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return cursor.getString(cursor.getColumnIndex(columnName)); 146624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 147624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 148624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private static int getInt(Cursor cursor, String columnName) { 149624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return cursor.getInt(cursor.getColumnIndex(columnName)); 150624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 151624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 152624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private static int getInt(Cursor cursor, String columnName, int missingValue) { 153624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final int columnIndex = cursor.getColumnIndex(columnName); 154624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return cursor.isNull(columnIndex) ? missingValue : cursor.getInt(columnIndex); 155624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 156624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 157624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private static long getLong(Cursor cursor, String columnName, long missingValue) { 158624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey final int columnIndex = cursor.getColumnIndex(columnName); 159624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return cursor.isNull(columnIndex) ? missingValue : cursor.getLong(columnIndex); 160624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 161624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey 162624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey private static boolean isNull(Cursor cursor, String columnName) { 163624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey return cursor.isNull(cursor.getColumnIndex(columnName)); 164624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey } 165624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey} 166