Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f517e7bb authored by Christine Chen's avatar Christine Chen
Browse files

Remove CallLog New and Old sectioning.

Bug: <5751629>
Change-Id: I1689fa10f285bc66fc69b6a9b9da139ce5461d83
parent 9d28cc4b
Loading
Loading
Loading
Loading
+2 −26
Original line number Diff line number Diff line
@@ -500,24 +500,10 @@ import java.util.LinkedList;
     */
    private void bindView(View view, Cursor c, int count) {
        final CallLogListItemViews views = (CallLogListItemViews) view.getTag();
        final int section = c.getInt(CallLogQuery.SECTION);

        // This might be a header: check the value of the section column in the cursor.
        if (section == CallLogQuery.SECTION_NEW_HEADER
                || section == CallLogQuery.SECTION_OLD_HEADER) {
            views.primaryActionView.setVisibility(View.GONE);
            views.bottomDivider.setVisibility(View.GONE);
            views.listHeaderTextView.setVisibility(View.VISIBLE);
            views.listHeaderTextView.setText(
                    section == CallLogQuery.SECTION_NEW_HEADER
                            ? R.string.call_log_new_header
                            : R.string.call_log_old_header);
            // Nothing else to set up for a header.
            return;
        }

        // Default case: an item in the call log.
        views.primaryActionView.setVisibility(View.VISIBLE);
        views.bottomDivider.setVisibility(isLastOfSection(c) ? View.GONE : View.VISIBLE);
        views.bottomDivider.setVisibility(View.VISIBLE);
        views.listHeaderTextView.setVisibility(View.GONE);

        final String number = c.getString(CallLogQuery.NUMBER);
@@ -617,16 +603,6 @@ import java.util.LinkedList;
        }
    }

    /** Returns true if this is the last item of a section. */
    private boolean isLastOfSection(Cursor c) {
        if (c.isLast()) return true;
        final int section = c.getInt(CallLogQuery.SECTION);
        if (!c.moveToNext()) return true;
        final int nextSection = c.getInt(CallLogQuery.SECTION);
        c.moveToPrevious();
        return section != nextSection;
    }

    /** Checks whether the contact info from the call log matches the one from the contacts db. */
    private boolean callLogInfoMatches(ContactInfo callLogInfo, ContactInfo info) {
        // The call log only contains a subset of the fields in the contacts db.
+1 −4
Original line number Diff line number Diff line
@@ -70,10 +70,7 @@ public class CallLogGroupBuilder {
            final boolean sameNumber = equalNumbers(firstNumber, currentNumber);
            final boolean shouldGroup;

            if (CallLogQuery.isSectionHeader(cursor)) {
                // Cannot group headers.
                shouldGroup = false;
            } else if (!sameNumber) {
            if (!sameNumber) {
                // Should only group with calls from the same number.
                shouldGroup = false;
            } else if (firstCallType == Calls.VOICEMAIL_TYPE) {
+0 −38
Original line number Diff line number Diff line
@@ -64,42 +64,4 @@ public final class CallLogQuery {
    public static final int CACHED_FORMATTED_NUMBER = 15;
    public static final int IS_READ = 16;
    public static final int NUMBER_PRESENTATION = 17;
    /** The index of the synthetic "section" column in the extended projection. */
    public static final int SECTION = 18;

    /**
     * The name of the synthetic "section" column.
     * <p>
     * This column identifies whether a row is a header or an actual item, and whether it is
     * part of the new or old calls.
     */
    public static final String SECTION_NAME = "section";
    /** The value of the "section" column for the header of the new section. */
    public static final int SECTION_NEW_HEADER = 0;
    /** The value of the "section" column for the items of the new section. */
    public static final int SECTION_NEW_ITEM = 1;
    /** The value of the "section" column for the header of the old section. */
    public static final int SECTION_OLD_HEADER = 2;
    /** The value of the "section" column for the items of the old section. */
    public static final int SECTION_OLD_ITEM = 3;

    /** The call log projection including the section name. */
    public static final String[] EXTENDED_PROJECTION;
    static {
        EXTENDED_PROJECTION = new String[_PROJECTION.length + 1];
        System.arraycopy(_PROJECTION, 0, EXTENDED_PROJECTION, 0, _PROJECTION.length);
        EXTENDED_PROJECTION[_PROJECTION.length] = SECTION_NAME;
    }

    public static boolean isSectionHeader(Cursor cursor) {
        int section = cursor.getInt(CallLogQuery.SECTION);
        return section == CallLogQuery.SECTION_NEW_HEADER
                || section == CallLogQuery.SECTION_OLD_HEADER;
    }

    public static boolean isNewSection(Cursor cursor) {
        int section = cursor.getInt(CallLogQuery.SECTION);
        return section == CallLogQuery.SECTION_NEW_ITEM
                || section == CallLogQuery.SECTION_NEW_HEADER;
    }
}
+18 −103
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import com.google.common.collect.Lists;

import java.lang.ref.WeakReference;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.annotation.concurrent.GuardedBy;

@@ -52,10 +51,8 @@ import javax.annotation.concurrent.GuardedBy;
    private static final String TAG = "CallLogQueryHandler";
    private static final int NUM_LOGS_TO_DISPLAY = 1000;

    /** The token for the query to fetch the new entries from the call log. */
    private static final int QUERY_NEW_CALLS_TOKEN = 53;
    /** The token for the query to fetch the old entries from the call log. */
    private static final int QUERY_OLD_CALLS_TOKEN = 54;
    private static final int QUERY_CALLLOG_TOKEN = 54;
    /** The token for the query to mark all missed calls as old after seeing the call log. */
    private static final int UPDATE_MARK_AS_OLD_TOKEN = 55;
    /** The token for the query to mark all new voicemails as old. */
@@ -71,24 +68,15 @@ import javax.annotation.concurrent.GuardedBy;
     */
    public static final int CALL_TYPE_ALL = -1;

    /**
     * The time window from the current time within which an unread entry will be added to the new
     * section.
     */
    private static final long NEW_SECTION_TIME_WINDOW = TimeUnit.DAYS.toMillis(7);

    private final WeakReference<Listener> mListener;

    /** The cursor containing the new calls, or null if they have not yet been fetched. */
    @GuardedBy("this") private Cursor mNewCallsCursor;
    /** The cursor containing the old calls, or null if they have not yet been fetched. */
    @GuardedBy("this") private Cursor mOldCallsCursor;
    @GuardedBy("this") private Cursor mCallLogCursor;
    /**
     * The identifier of the latest calls request.
     * <p>
     * A request for the list of calls requires two queries and hence the two cursor
     * {@link #mNewCallsCursor} and {@link #mOldCallsCursor} above, corresponding to
     * {@link #QUERY_NEW_CALLS_TOKEN} and {@link #QUERY_OLD_CALLS_TOKEN}.
     * and {@link #mCallLogCursor} above, corresponding to {@link #QUERY_CALLLOG_TOKEN}.
     * <p>
     * When a new request is about to be started, existing cursors are closed. However, it is
     * possible that one of the queries completes after the new request has started. This means that
@@ -137,29 +125,6 @@ import javax.annotation.concurrent.GuardedBy;
        mListener = new WeakReference<Listener>(listener);
    }

    /** Creates a cursor that contains a single row and maps the section to the given value. */
    private Cursor createHeaderCursorFor(int section) {
        MatrixCursor matrixCursor =
                new MatrixCursor(CallLogQuery.EXTENDED_PROJECTION);
        // The values in this row correspond to default values for _PROJECTION from CallLogQuery
        // plus the section value.
        matrixCursor.addRow(new Object[]{
                0L, "", 0L, 0L, 0, "", "", "", null, 0, null, null, null, null, 0L, null, 0,
                Calls.PRESENTATION_ALLOWED, section
        });
        return matrixCursor;
    }

    /** Returns a cursor for the old calls header. */
    private Cursor createOldCallsHeaderCursor() {
        return createHeaderCursorFor(CallLogQuery.SECTION_OLD_HEADER);
    }

    /** Returns a cursor for the new calls header. */
    private Cursor createNewCallsHeaderCursor() {
        return createHeaderCursorFor(CallLogQuery.SECTION_NEW_HEADER);
    }

    /**
     * Fetches the list of calls from the call log for a given type.
     * <p>
@@ -168,8 +133,7 @@ import javax.annotation.concurrent.GuardedBy;
    public void fetchCalls(int callType) {
        cancelFetch();
        int requestId = newCallsRequest();
        fetchCalls(QUERY_NEW_CALLS_TOKEN, requestId, true /*isNew*/, callType);
        fetchCalls(QUERY_OLD_CALLS_TOKEN, requestId, false /*isNew*/, callType);
        fetchCalls(QUERY_CALLLOG_TOKEN, requestId, callType);
    }

    public void fetchVoicemailStatus() {
@@ -178,21 +142,16 @@ import javax.annotation.concurrent.GuardedBy;
    }

    /** Fetches the list of calls in the call log, either the new one or the old ones. */
    private void fetchCalls(int token, int requestId, boolean isNew, int callType) {
    private void fetchCalls(int token, int requestId, int callType) {
        // We need to check for NULL explicitly otherwise entries with where READ is NULL
        // may not match either the query or its negation.
        // We consider the calls that are not yet consumed (i.e. IS_READ = 0) as "new".
        String selection = String.format("%s IS NOT NULL AND %s = 0 AND %s > ?",
                Calls.IS_READ, Calls.IS_READ, Calls.DATE);
        List<String> selectionArgs = Lists.newArrayList(
                Long.toString(System.currentTimeMillis() - NEW_SECTION_TIME_WINDOW));
        if (!isNew) {
            // Negate the query.
            selection = String.format("NOT (%s)", selection);
        }
        String selection = null;
        List<String> selectionArgs = Lists.newArrayList();

        if (callType > CALL_TYPE_ALL) {
            // Add a clause to fetch only items of type voicemail.
            selection = String.format("(%s) AND (%s = ?)", selection, Calls.TYPE);
            selection = String.format("(%s = ?)", Calls.TYPE);
            selectionArgs.add(Integer.toString(callType));
        }
        Uri uri = Calls.CONTENT_URI_WITH_VOICEMAIL.buildUpon()
@@ -205,8 +164,7 @@ import javax.annotation.concurrent.GuardedBy;

    /** Cancel any pending fetch request. */
    private void cancelFetch() {
        cancelOperation(QUERY_NEW_CALLS_TOKEN);
        cancelOperation(QUERY_OLD_CALLS_TOKEN);
        cancelOperation(QUERY_CALLLOG_TOKEN);
    }

    /** Updates all new calls to mark them as old. */
@@ -261,16 +219,14 @@ import javax.annotation.concurrent.GuardedBy;
     * Closes any open cursor that has not yet been sent to the requester.
     */
    private synchronized int newCallsRequest() {
        MoreCloseables.closeQuietly(mNewCallsCursor);
        MoreCloseables.closeQuietly(mOldCallsCursor);
        mNewCallsCursor = null;
        mOldCallsCursor = null;
        MoreCloseables.closeQuietly(mCallLogCursor);
        mCallLogCursor = null;
        return ++mCallsRequestId;
    }

    @Override
    protected void onNotNullableQueryComplete(int token, Object cookie, Cursor cursor) {
        if (token == QUERY_NEW_CALLS_TOKEN) {
        if (token == QUERY_CALLLOG_TOKEN) {
            int requestId = ((Integer) cookie).intValue();
            if (requestId != mCallsRequestId) {
                // Ignore this query since it does not correspond to the latest request.
@@ -278,20 +234,8 @@ import javax.annotation.concurrent.GuardedBy;
            }

            // Store the returned cursor.
            MoreCloseables.closeQuietly(mNewCallsCursor);
            mNewCallsCursor = new ExtendedCursor(
                    cursor, CallLogQuery.SECTION_NAME, CallLogQuery.SECTION_NEW_ITEM);
        } else if (token == QUERY_OLD_CALLS_TOKEN) {
            int requestId = ((Integer) cookie).intValue();
            if (requestId != mCallsRequestId) {
                // Ignore this query since it does not correspond to the latest request.
                return;
            }

            // Store the returned cursor.
            MoreCloseables.closeQuietly(mOldCallsCursor);
            mOldCallsCursor = new ExtendedCursor(
                    cursor, CallLogQuery.SECTION_NAME, CallLogQuery.SECTION_OLD_ITEM);
            MoreCloseables.closeQuietly(mCallLogCursor);
            mCallLogCursor = cursor;
        } else if (token == QUERY_VOICEMAIL_STATUS_TOKEN) {
            updateVoicemailStatus(cursor);
            return;
@@ -300,38 +244,9 @@ import javax.annotation.concurrent.GuardedBy;
            return;
        }

        if (mNewCallsCursor != null && mOldCallsCursor != null) {
            updateAdapterData(createMergedCursor());
        }
    }

    /** Creates the merged cursor representing the data to show in the call log. */
    @GuardedBy("this")
    private Cursor createMergedCursor() {
        try {
            final boolean hasNewCalls = mNewCallsCursor.getCount() != 0;
            final boolean hasOldCalls = mOldCallsCursor.getCount() != 0;

            if (!hasNewCalls) {
                // Return only the old calls, without the header.
                MoreCloseables.closeQuietly(mNewCallsCursor);
                return mOldCallsCursor;
            }

            if (!hasOldCalls) {
                // Return only the new calls.
                MoreCloseables.closeQuietly(mOldCallsCursor);
                return new MergeCursor(
                        new Cursor[]{ createNewCallsHeaderCursor(), mNewCallsCursor });
            }

            return new MergeCursor(new Cursor[]{
                    createNewCallsHeaderCursor(), mNewCallsCursor,
                    createOldCallsHeaderCursor(), mOldCallsCursor});
        } finally {
            // Any cursor still open is now owned, directly or indirectly, by the caller.
            mNewCallsCursor = null;
            mOldCallsCursor = null;
        if (mCallLogCursor != null) {
            updateAdapterData(mCallLogCursor);
            mCallLogCursor = null;
        }
    }

+0 −154
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.dialer.calllog;

import android.database.AbstractCursor;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DataSetObserver;

import com.android.common.io.MoreCloseables;

/**
 * Wraps a cursor to add an additional column with the same value for all rows.
 * <p>
 * The number of rows in the cursor and the set of columns is determined by the cursor being
 * wrapped.
 */
public class ExtendedCursor extends AbstractCursor {
    /** The cursor to wrap. */
    private final Cursor mCursor;
    /** The name of the additional column. */
    private final String mColumnName;
    /** The value to be assigned to the additional column. */
    private final Object mValue;

    /**
     * Creates a new cursor which extends the given cursor by adding a column with a constant value.
     *
     * @param cursor the cursor to extend
     * @param columnName the name of the additional column
     * @param value the value to be assigned to the additional column
     */
    public ExtendedCursor(Cursor cursor, String columnName, Object value) {
        mCursor = cursor;
        mColumnName = columnName;
        mValue = value;
    }

    @Override
    public int getCount() {
        return mCursor.getCount();
    }

    @Override
    public String[] getColumnNames() {
        String[] columnNames = mCursor.getColumnNames();
        int length = columnNames.length;
        String[] extendedColumnNames = new String[length + 1];
        System.arraycopy(columnNames, 0, extendedColumnNames, 0, length);
        extendedColumnNames[length] = mColumnName;
        return extendedColumnNames;
    }

    @Override
    public String getString(int column) {
        if (column == mCursor.getColumnCount()) {
            return (String) mValue;
        }
        return mCursor.getString(column);
    }

    @Override
    public short getShort(int column) {
        if (column == mCursor.getColumnCount()) {
            return (Short) mValue;
        }
        return mCursor.getShort(column);
    }

    @Override
    public int getInt(int column) {
        if (column == mCursor.getColumnCount()) {
            return (Integer) mValue;
        }
        return mCursor.getInt(column);
    }

    @Override
    public long getLong(int column) {
        if (column == mCursor.getColumnCount()) {
            return (Long) mValue;
        }
        return mCursor.getLong(column);
    }

    @Override
    public float getFloat(int column) {
        if (column == mCursor.getColumnCount()) {
            return (Float) mValue;
        }
        return mCursor.getFloat(column);
    }

    @Override
    public double getDouble(int column) {
        if (column == mCursor.getColumnCount()) {
            return (Double) mValue;
        }
        return mCursor.getDouble(column);
    }

    @Override
    public boolean isNull(int column) {
        if (column == mCursor.getColumnCount()) {
            return mValue == null;
        }
        return mCursor.isNull(column);
    }

    @Override
    public boolean onMove(int oldPosition, int newPosition) {
        return mCursor.moveToPosition(newPosition);
    }

    @Override
    public void close() {
        MoreCloseables.closeQuietly(mCursor);
        super.close();
    }

    @Override
    public void registerContentObserver(ContentObserver observer) {
        mCursor.registerContentObserver(observer);
    }

    @Override
    public void unregisterContentObserver(ContentObserver observer) {
        mCursor.unregisterContentObserver(observer);
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        mCursor.registerDataSetObserver(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        mCursor.unregisterDataSetObserver(observer);
    }
}
Loading