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

Commit e0296a72 authored by linyuh's avatar linyuh Committed by android-build-merger
Browse files

Merge "Move coalescing logic out of AnnotatedCallLogContentProvider." am: 21f2f3e1

am: 11af04d7

Change-Id: Ic35e2ce475d6c99ad06dfc070fec662935393bc0
parents 8fb18327 11af04d7
Loading
Loading
Loading
Loading
+1 −49
Original line number Original line Diff line number Diff line
@@ -29,16 +29,12 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.net.Uri;
import android.os.Build;
import android.os.Build;
import android.provider.CallLog.Calls;
import android.support.annotation.NonNull;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Nullable;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
import com.android.dialer.common.Assert;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.LogUtil;
import com.android.dialer.metrics.Metrics;
import com.android.dialer.metrics.MetricsComponent;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;


@@ -50,7 +46,6 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
  private static final int ANNOTATED_CALL_LOG_TABLE_CODE = 1;
  private static final int ANNOTATED_CALL_LOG_TABLE_CODE = 1;
  private static final int ANNOTATED_CALL_LOG_TABLE_ID_CODE = 2;
  private static final int ANNOTATED_CALL_LOG_TABLE_ID_CODE = 2;
  private static final int ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE = 3;
  private static final int ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE = 3;
  private static final int COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE = 4;


  private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);


@@ -65,10 +60,6 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
        AnnotatedCallLogContract.AUTHORITY,
        AnnotatedCallLogContract.AUTHORITY,
        AnnotatedCallLog.DISTINCT_PHONE_NUMBERS,
        AnnotatedCallLog.DISTINCT_PHONE_NUMBERS,
        ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE);
        ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE);
    uriMatcher.addURI(
        AnnotatedCallLogContract.AUTHORITY,
        CoalescedAnnotatedCallLog.TABLE,
        COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE);
  }
  }


  private AnnotatedCallLogDatabaseHelper databaseHelper;
  private AnnotatedCallLogDatabaseHelper databaseHelper;
@@ -142,33 +133,6 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
          LogUtil.w("AnnotatedCallLogContentProvider.query", "cursor was null");
          LogUtil.w("AnnotatedCallLogContentProvider.query", "cursor was null");
        }
        }
        return cursor;
        return cursor;
      case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE:
        Assert.checkArgument(
            projection == CoalescedAnnotatedCallLog.ALL_COLUMNS,
            "only ALL_COLUMNS projection supported for coalesced call log");
        Assert.checkArgument(selection == null, "selection not supported for coalesced call log");
        Assert.checkArgument(
            selectionArgs == null, "selection args not supported for coalesced call log");
        Assert.checkArgument(sortOrder == null, "sort order not supported for coalesced call log");
        MetricsComponent.get(getContext()).metrics().startTimer(Metrics.NEW_CALL_LOG_COALESCE);
        try (Cursor allAnnotatedCallLogRows =
            queryBuilder.query(
                db,
                null,
                String.format("%s != ?", CoalescedAnnotatedCallLog.CALL_TYPE),
                new String[] {Integer.toString(Calls.VOICEMAIL_TYPE)},
                null,
                null,
                AnnotatedCallLog.TIMESTAMP + " DESC")) {
          Cursor coalescedRows =
              CallLogDatabaseComponent.get(getContext())
                  .coalescer()
                  .coalesce(allAnnotatedCallLogRows);
          coalescedRows.setNotificationUri(
              getContext().getContentResolver(), CoalescedAnnotatedCallLog.CONTENT_URI);
          MetricsComponent.get(getContext()).metrics().stopTimer(Metrics.NEW_CALL_LOG_COALESCE);
          return coalescedRows;
        }
      default:
      default:
        throw new IllegalArgumentException("Unknown uri: " + uri);
        throw new IllegalArgumentException("Unknown uri: " + uri);
    }
    }
@@ -207,8 +171,6 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
        break;
        break;
      case ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE:
      case ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE:
        throw new UnsupportedOperationException();
        throw new UnsupportedOperationException();
      case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE:
        throw new UnsupportedOperationException("coalesced call log does not support inserting");
      default:
      default:
        throw new IllegalArgumentException("Unknown uri: " + uri);
        throw new IllegalArgumentException("Unknown uri: " + uri);
    }
    }
@@ -245,8 +207,6 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
        break;
        break;
      case ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE:
      case ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE:
        throw new UnsupportedOperationException();
        throw new UnsupportedOperationException();
      case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE:
        throw new UnsupportedOperationException("coalesced call log does not support deleting");
      default:
      default:
        throw new IllegalArgumentException("Unknown uri: " + uri);
        throw new IllegalArgumentException("Unknown uri: " + uri);
    }
    }
@@ -300,7 +260,6 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
        }
        }
        return rows;
        return rows;
      case ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE:
      case ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE:
      case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE:
        throw new UnsupportedOperationException();
        throw new UnsupportedOperationException();
      default:
      default:
        throw new IllegalArgumentException("Unknown uri: " + uri);
        throw new IllegalArgumentException("Unknown uri: " + uri);
@@ -336,9 +295,6 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
            break;
            break;
          case ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE:
          case ANNOTATED_CALL_LOG_TABLE_DISTINCT_NUMBER_CODE:
            throw new UnsupportedOperationException();
            throw new UnsupportedOperationException();
          case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE:
            throw new UnsupportedOperationException(
                "coalesced call log does not support applyBatch");
          default:
          default:
            throw new IllegalArgumentException("Unknown uri: " + operation.getUri());
            throw new IllegalArgumentException("Unknown uri: " + operation.getUri());
        }
        }
@@ -380,10 +336,6 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
  }
  }


  private void notifyChange(Uri uri) {
  private void notifyChange(Uri uri) {
    getContext().getContentResolver().notifyChange(uri, null);
    getContext().getContentResolver().notifyChange(uri, /* observer = */ null);
    // Any time the annotated call log changes, we need to also notify observers of the
    // CoalescedAnnotatedCallLog, since that is just a massaged in-memory view of the real annotated
    // call log table.
    getContext().getContentResolver().notifyChange(CoalescedAnnotatedCallLog.CONTENT_URI, null);
  }
  }
}
}
+142 −9
Original line number Original line Diff line number Diff line
@@ -22,17 +22,25 @@ import android.provider.CallLog.Calls;
import android.support.annotation.NonNull;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
import android.support.annotation.WorkerThread;
import android.telecom.PhoneAccountHandle;
import android.telecom.PhoneAccountHandle;
import android.text.TextUtils;
import com.android.dialer.CoalescedIds;
import com.android.dialer.CoalescedIds;
import com.android.dialer.DialerPhoneNumber;
import com.android.dialer.DialerPhoneNumber;
import com.android.dialer.NumberAttributes;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
import com.android.dialer.calllog.datasources.CallLogDataSource;
import com.android.dialer.calllog.datasources.CallLogDataSource;
import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.calllog.model.CoalescedRow;
import com.android.dialer.common.Assert;
import com.android.dialer.common.Assert;
import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
import com.android.dialer.metrics.FutureTimer;
import com.android.dialer.metrics.Metrics;
import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
import com.android.dialer.telecom.TelecomUtil;
import com.android.dialer.telecom.TelecomUtil;
import com.google.common.base.Preconditions;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
@@ -41,32 +49,76 @@ import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Inject;


/**
/**
 * Coalesces call log rows by combining some adjacent rows.
 * Coalesces rows in {@link AnnotatedCallLog} by combining adjacent rows.
 *
 *
 * <p>Applies the logic that determines which adjacent rows should be coalesced, and then delegates
 * <p>Applies the logic that determines which adjacent rows should be coalesced, and then delegates
 * to each data source to determine how individual columns should be aggregated.
 * to each data source to determine how individual columns should be aggregated.
 */
 */
public class Coalescer {
public class Coalescer {

  // Indexes for CoalescedAnnotatedCallLog.ALL_COLUMNS
  private static final int ID = 0;
  private static final int TIMESTAMP = 1;
  private static final int NUMBER = 2;
  private static final int FORMATTED_NUMBER = 3;
  private static final int NUMBER_PRESENTATION = 4;
  private static final int IS_READ = 5;
  private static final int NEW = 6;
  private static final int GEOCODED_LOCATION = 7;
  private static final int PHONE_ACCOUNT_COMPONENT_NAME = 8;
  private static final int PHONE_ACCOUNT_ID = 9;
  private static final int FEATURES = 10;
  private static final int NUMBER_ATTRIBUTES = 11;
  private static final int IS_VOICEMAIL_CALL = 12;
  private static final int VOICEMAIL_CALL_TAG = 13;
  private static final int CALL_TYPE = 14;
  private static final int COALESCED_IDS = 15;

  private final DataSources dataSources;
  private final DataSources dataSources;
  private final FutureTimer futureTimer;
  private final ListeningExecutorService backgroundExecutorService;


  @Inject
  @Inject
  Coalescer(DataSources dataSources) {
  Coalescer(
      @BackgroundExecutor ListeningExecutorService backgroundExecutorService,
      DataSources dataSources,
      FutureTimer futureTimer) {
    this.backgroundExecutorService = backgroundExecutorService;
    this.dataSources = dataSources;
    this.dataSources = dataSources;
    this.futureTimer = futureTimer;
  }

  /**
   * Given rows from {@link AnnotatedCallLog}, combine adjacent ones which should be collapsed for
   * display purposes.
   *
   * @param allAnnotatedCallLogRowsSortedByTimestampDesc {@link AnnotatedCallLog} rows sorted in
   *     descending order of timestamp.
   * @return a future of a {@link MatrixCursor} containing the {@link CoalescedAnnotatedCallLog}
   *     rows to display
   */
  public ListenableFuture<Cursor> coalesce(
      @NonNull Cursor allAnnotatedCallLogRowsSortedByTimestampDesc) {
    ListenableFuture<Cursor> coalescingFuture =
        backgroundExecutorService.submit(
            () -> coalesceInternal(Assert.isNotNull(allAnnotatedCallLogRowsSortedByTimestampDesc)));
    futureTimer.applyTiming(coalescingFuture, Metrics.NEW_CALL_LOG_COALESCE);
    return coalescingFuture;
  }
  }


  /**
  /**
   * Reads the entire {@link AnnotatedCallLog} database into memory from the provided {@code
   * Reads the entire {@link AnnotatedCallLog} into memory from the provided cursor and then builds
   * allAnnotatedCallLog} parameter and then builds and returns a new {@link MatrixCursor} which is
   * and returns a new {@link MatrixCursor} of {@link CoalescedAnnotatedCallLog}, which is the
   * the result of combining adjacent rows which should be collapsed for display purposes.
   * result of combining adjacent rows which should be collapsed for display purposes.
   *
   *
   * @param allAnnotatedCallLogRowsSortedByTimestampDesc all {@link AnnotatedCallLog} rows, sorted
   * @param allAnnotatedCallLogRowsSortedByTimestampDesc {@link AnnotatedCallLog} rows sorted in
   *     by timestamp descending
   *     descending order of timestamp.
   * @return a new {@link MatrixCursor} containing the {@link CoalescedAnnotatedCallLog} rows to
   * @return a new {@link MatrixCursor} containing the {@link CoalescedAnnotatedCallLog} rows to
   *     display
   *     display
   */
   */
  @WorkerThread
  @WorkerThread
  @NonNull
  @NonNull
  Cursor coalesce(@NonNull Cursor allAnnotatedCallLogRowsSortedByTimestampDesc) {
  private Cursor coalesceInternal(Cursor allAnnotatedCallLogRowsSortedByTimestampDesc) {
    Assert.isWorkerThread();
    Assert.isWorkerThread();


    // Note: This method relies on rowsShouldBeCombined to determine which rows should be combined,
    // Note: This method relies on rowsShouldBeCombined to determine which rows should be combined,
@@ -77,7 +129,7 @@ public class Coalescer {
    MatrixCursor allCoalescedRowsMatrixCursor =
    MatrixCursor allCoalescedRowsMatrixCursor =
        new MatrixCursor(
        new MatrixCursor(
            CoalescedAnnotatedCallLog.ALL_COLUMNS,
            CoalescedAnnotatedCallLog.ALL_COLUMNS,
            Assert.isNotNull(allAnnotatedCallLogRowsSortedByTimestampDesc).getCount());
            allAnnotatedCallLogRowsSortedByTimestampDesc.getCount());


    if (!allAnnotatedCallLogRowsSortedByTimestampDesc.moveToFirst()) {
    if (!allAnnotatedCallLogRowsSortedByTimestampDesc.moveToFirst()) {
      return allCoalescedRowsMatrixCursor;
      return allCoalescedRowsMatrixCursor;
@@ -252,4 +304,85 @@ public class Coalescer {
      rowBuilder.add(entry.getKey(), entry.getValue());
      rowBuilder.add(entry.getKey(), entry.getValue());
    }
    }
  }
  }

  /**
   * Creates a new {@link CoalescedRow} based on the data at the provided cursor's current position.
   *
   * <p>The provided cursor should be one for {@link CoalescedAnnotatedCallLog}.
   */
  public static CoalescedRow toRow(Cursor coalescedAnnotatedCallLogCursor) {
    DialerPhoneNumber number;
    try {
      number = DialerPhoneNumber.parseFrom(coalescedAnnotatedCallLogCursor.getBlob(NUMBER));
    } catch (InvalidProtocolBufferException e) {
      throw new IllegalStateException("Couldn't parse DialerPhoneNumber bytes");
    }

    CoalescedIds coalescedIds;
    try {
      coalescedIds = CoalescedIds.parseFrom(coalescedAnnotatedCallLogCursor.getBlob(COALESCED_IDS));
    } catch (InvalidProtocolBufferException e) {
      throw new IllegalStateException("Couldn't parse CoalescedIds bytes");
    }

    NumberAttributes numberAttributes;
    try {
      numberAttributes =
          NumberAttributes.parseFrom(coalescedAnnotatedCallLogCursor.getBlob(NUMBER_ATTRIBUTES));
    } catch (InvalidProtocolBufferException e) {
      throw new IllegalStateException("Couldn't parse NumberAttributes bytes");
    }

    CoalescedRow.Builder coalescedRowBuilder =
        CoalescedRow.newBuilder()
            .setId(coalescedAnnotatedCallLogCursor.getLong(ID))
            .setTimestamp(coalescedAnnotatedCallLogCursor.getLong(TIMESTAMP))
            .setNumber(number)
            .setNumberPresentation(coalescedAnnotatedCallLogCursor.getInt(NUMBER_PRESENTATION))
            .setIsRead(coalescedAnnotatedCallLogCursor.getInt(IS_READ) == 1)
            .setIsNew(coalescedAnnotatedCallLogCursor.getInt(NEW) == 1)
            .setFeatures(coalescedAnnotatedCallLogCursor.getInt(FEATURES))
            .setCallType(coalescedAnnotatedCallLogCursor.getInt(CALL_TYPE))
            .setNumberAttributes(numberAttributes)
            .setIsVoicemailCall(coalescedAnnotatedCallLogCursor.getInt(IS_VOICEMAIL_CALL) == 1)
            .setCoalescedIds(coalescedIds);

    String formattedNumber = coalescedAnnotatedCallLogCursor.getString(FORMATTED_NUMBER);
    if (!TextUtils.isEmpty(formattedNumber)) {
      coalescedRowBuilder.setFormattedNumber(formattedNumber);
    }

    String geocodedLocation = coalescedAnnotatedCallLogCursor.getString(GEOCODED_LOCATION);
    if (!TextUtils.isEmpty(geocodedLocation)) {
      coalescedRowBuilder.setGeocodedLocation(geocodedLocation);
    }

    String phoneAccountComponentName =
        coalescedAnnotatedCallLogCursor.getString(PHONE_ACCOUNT_COMPONENT_NAME);
    if (!TextUtils.isEmpty(phoneAccountComponentName)) {
      coalescedRowBuilder.setPhoneAccountComponentName(
          coalescedAnnotatedCallLogCursor.getString(PHONE_ACCOUNT_COMPONENT_NAME));
    }

    String phoneAccountId = coalescedAnnotatedCallLogCursor.getString(PHONE_ACCOUNT_ID);
    if (!TextUtils.isEmpty(phoneAccountId)) {
      coalescedRowBuilder.setPhoneAccountId(phoneAccountId);
    }

    String voicemailCallTag = coalescedAnnotatedCallLogCursor.getString(VOICEMAIL_CALL_TAG);
    if (!TextUtils.isEmpty(voicemailCallTag)) {
      coalescedRowBuilder.setVoicemailCallTag(voicemailCallTag);
    }

    return coalescedRowBuilder.build();
  }

  /**
   * Returns the timestamp at the provided cursor's current position.
   *
   * <p>The provided cursor should be one for {@link CoalescedAnnotatedCallLog}.
   */
  public static long getTimestamp(Cursor coalescedAnnotatedCallLogCursor) {
    return coalescedAnnotatedCallLogCursor.getLong(TIMESTAMP);
  }
}
}
+1 −11
Original line number Original line Diff line number Diff line
@@ -225,7 +225,7 @@ public class AnnotatedCallLogContract {
    /**
    /**
     * An unique id to associate this call log row to a {@link android.telecom.Call}.
     * An unique id to associate this call log row to a {@link android.telecom.Call}.
     *
     *
     * <p>For pre-Q device, this is same as {@link TIMESTAMP}.
     * <p>For pre-Q device, this is same as {@link #TIMESTAMP}.
     *
     *
     * <p>For Q+ device, this will be copied from {@link android.provider.CallLog.Calls}.
     * <p>For Q+ device, this will be copied from {@link android.provider.CallLog.Calls}.
     *
     *
@@ -244,16 +244,6 @@ public class AnnotatedCallLogContract {
   */
   */
  public static final class CoalescedAnnotatedCallLog implements CommonColumns {
  public static final class CoalescedAnnotatedCallLog implements CommonColumns {


    public static final String TABLE = "CoalescedAnnotatedCallLog";

    /** The content URI for this table. */
    public static final Uri CONTENT_URI =
        Uri.withAppendedPath(AnnotatedCallLogContract.CONTENT_URI, TABLE);

    /** The MIME type of a {@link android.content.ContentProvider#getType(Uri)} single entry. */
    public static final String CONTENT_ITEM_TYPE =
        "vnd.android.cursor.item/coalesced_annotated_call_log";

    /**
    /**
     * IDs of rows in {@link AnnotatedCallLog} that are coalesced into one row in {@link
     * IDs of rows in {@link AnnotatedCallLog} that are coalesced into one row in {@link
     * CoalescedAnnotatedCallLog}, encoded as a {@link com.android.dialer.CoalescedIds} proto.
     * CoalescedAnnotatedCallLog}, encoded as a {@link com.android.dialer.CoalescedIds} proto.
+36 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 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.ui;

import android.content.Context;
import android.provider.CallLog.Calls;
import android.support.v4.content.CursorLoader;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;

/** Cursor loader for {@link AnnotatedCallLog}. */
final class AnnotatedCallLogCursorLoader extends CursorLoader {

  AnnotatedCallLogCursorLoader(Context context) {
    super(
        context,
        AnnotatedCallLog.CONTENT_URI,
        /* projection = */ null,
        /* selection = */ AnnotatedCallLog.CALL_TYPE + " != ?",
        /* selectionArgs = */ new String[] {Integer.toString(Calls.VOICEMAIL_TYPE)},
        /* sortOrder = */ AnnotatedCallLog.TIMESTAMP + " DESC");
  }
}
+0 −132
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 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.ui;

import android.content.Context;
import android.database.Cursor;
import android.support.v4.content.CursorLoader;
import android.text.TextUtils;
import com.android.dialer.CoalescedIds;
import com.android.dialer.DialerPhoneNumber;
import com.android.dialer.NumberAttributes;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
import com.android.dialer.calllog.model.CoalescedRow;
import com.google.protobuf.InvalidProtocolBufferException;

/** CursorLoader for the coalesced annotated call log. */
final class CoalescedAnnotatedCallLogCursorLoader extends CursorLoader {

  // Indexes for CoalescedAnnotatedCallLog.ALL_COLUMNS
  private static final int ID = 0;
  private static final int TIMESTAMP = 1;
  private static final int NUMBER = 2;
  private static final int FORMATTED_NUMBER = 3;
  private static final int NUMBER_PRESENTATION = 4;
  private static final int IS_READ = 5;
  private static final int NEW = 6;
  private static final int GEOCODED_LOCATION = 7;
  private static final int PHONE_ACCOUNT_COMPONENT_NAME = 8;
  private static final int PHONE_ACCOUNT_ID = 9;
  private static final int FEATURES = 10;
  private static final int NUMBER_ATTRIBUTES = 11;
  private static final int IS_VOICEMAIL_CALL = 12;
  private static final int VOICEMAIL_CALL_TAG = 13;
  private static final int CALL_TYPE = 14;
  private static final int COALESCED_IDS = 15;

  CoalescedAnnotatedCallLogCursorLoader(Context context) {
    // CoalescedAnnotatedCallLog requires that PROJECTION be ALL_COLUMNS and the following params be
    // null.
    super(
        context,
        CoalescedAnnotatedCallLog.CONTENT_URI,
        CoalescedAnnotatedCallLog.ALL_COLUMNS,
        null,
        null,
        null);
  }

  /** Creates a new {@link CoalescedRow} from the provided cursor using the current position. */
  static CoalescedRow toRow(Cursor cursor) {
    DialerPhoneNumber number;
    try {
      number = DialerPhoneNumber.parseFrom(cursor.getBlob(NUMBER));
    } catch (InvalidProtocolBufferException e) {
      throw new IllegalStateException("Couldn't parse DialerPhoneNumber bytes");
    }

    CoalescedIds coalescedIds;
    try {
      coalescedIds = CoalescedIds.parseFrom(cursor.getBlob(COALESCED_IDS));
    } catch (InvalidProtocolBufferException e) {
      throw new IllegalStateException("Couldn't parse CoalescedIds bytes");
    }

    NumberAttributes numberAttributes;
    try {
      numberAttributes = NumberAttributes.parseFrom(cursor.getBlob(NUMBER_ATTRIBUTES));
    } catch (InvalidProtocolBufferException e) {
      throw new IllegalStateException("Couldn't parse NumberAttributes bytes");
    }

    CoalescedRow.Builder coalescedRowBuilder =
        CoalescedRow.newBuilder()
            .setId(cursor.getLong(ID))
            .setTimestamp(cursor.getLong(TIMESTAMP))
            .setNumber(number)
            .setNumberPresentation(cursor.getInt(NUMBER_PRESENTATION))
            .setIsRead(cursor.getInt(IS_READ) == 1)
            .setIsNew(cursor.getInt(NEW) == 1)
            .setFeatures(cursor.getInt(FEATURES))
            .setCallType(cursor.getInt(CALL_TYPE))
            .setNumberAttributes(numberAttributes)
            .setIsVoicemailCall(cursor.getInt(IS_VOICEMAIL_CALL) == 1)
            .setCoalescedIds(coalescedIds);

    String formattedNumber = cursor.getString(FORMATTED_NUMBER);
    if (!TextUtils.isEmpty(formattedNumber)) {
      coalescedRowBuilder.setFormattedNumber(formattedNumber);
    }

    String geocodedLocation = cursor.getString(GEOCODED_LOCATION);
    if (!TextUtils.isEmpty(geocodedLocation)) {
      coalescedRowBuilder.setGeocodedLocation(geocodedLocation);
    }

    String phoneAccountComponentName = cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME);
    if (!TextUtils.isEmpty(phoneAccountComponentName)) {
      coalescedRowBuilder.setPhoneAccountComponentName(
          cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME));
    }

    String phoneAccountId = cursor.getString(PHONE_ACCOUNT_ID);
    if (!TextUtils.isEmpty(phoneAccountId)) {
      coalescedRowBuilder.setPhoneAccountId(phoneAccountId);
    }

    String voicemailCallTag = cursor.getString(VOICEMAIL_CALL_TAG);
    if (!TextUtils.isEmpty(voicemailCallTag)) {
      coalescedRowBuilder.setVoicemailCallTag(voicemailCallTag);
    }

    return coalescedRowBuilder.build();
  }

  static long getTimestamp(Cursor cursor) {
    return cursor.getLong(TIMESTAMP);
  }
}
Loading