summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/calllog
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/calllog')
-rw-r--r--java/com/android/dialer/calllog/CallLogComponent.java2
-rw-r--r--java/com/android/dialer/calllog/CallLogFramework.java24
-rw-r--r--java/com/android/dialer/calllog/CallLogModule.java8
-rw-r--r--java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java123
-rw-r--r--java/com/android/dialer/calllog/database/AndroidManifest.xml28
-rw-r--r--java/com/android/dialer/calllog/database/AnnotatedCallLog.java53
-rw-r--r--java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java333
-rw-r--r--java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java64
-rw-r--r--java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java40
-rw-r--r--java/com/android/dialer/calllog/database/CallLogMutations.java58
-rw-r--r--java/com/android/dialer/calllog/database/Coalescer.java194
-rw-r--r--java/com/android/dialer/calllog/database/MutationApplier.java105
-rw-r--r--java/com/android/dialer/calllog/database/annotated_call_log.proto15
-rw-r--r--java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java259
-rw-r--r--java/com/android/dialer/calllog/datasources/CallLogDataSource.java67
-rw-r--r--java/com/android/dialer/calllog/datasources/CallLogMutations.java110
-rw-r--r--java/com/android/dialer/calllog/datasources/DataSources.java (renamed from java/com/android/dialer/calllog/DataSources.java)5
-rw-r--r--java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java24
-rw-r--r--java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java359
-rw-r--r--java/com/android/dialer/calllog/datasources/util/RowCombiner.java73
-rw-r--r--java/com/android/dialer/calllog/ui/AndroidManifest.xml2
-rw-r--r--java/com/android/dialer/calllog/ui/AnnotatedCallLogCursorLoader.java48
-rw-r--r--java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java151
-rw-r--r--java/com/android/dialer/calllog/ui/HeaderViewHolder.java36
-rw-r--r--java/com/android/dialer/calllog/ui/NewCallLogAdapter.java155
-rw-r--r--java/com/android/dialer/calllog/ui/NewCallLogFragment.java110
-rw-r--r--java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java175
-rw-r--r--java/com/android/dialer/calllog/ui/res/layout/new_call_log_entry.xml100
-rw-r--r--java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml7
-rw-r--r--java/com/android/dialer/calllog/ui/res/layout/new_call_log_header.xml29
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-af/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-am/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ar/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-az/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-b+sr+Latn/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-be/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-bg/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-bn/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-bs/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ca/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-cs/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-da/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-de/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-el/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-en-rAU/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-en-rGB/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-en-rIN/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-es-rUS/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-es/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-et/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-eu/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-fa/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-fi/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-fr-rCA/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-fr/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-gl/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-gu/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-hi/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-hr/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-hu/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-hy/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-in/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-is/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-it/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-iw/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ja/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ka/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-kk/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-km/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-kn/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ko/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ky/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-lo/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-lt/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-lv/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-mk/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ml/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-mn/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-mr/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ms/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-my/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-nb/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ne/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-nl/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-no/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-pa/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-pl/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-pt-rBR/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-pt-rPT/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-pt/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ro/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ru/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-si/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-sk/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-sl/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-sq/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-sr/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-sv/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-sw/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ta/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-te/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-th/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-tl/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-tr/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-uk/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-ur/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-uz/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-vi/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-zh-rCN/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-zh-rHK/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-zh-rTW/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values-zu/strings.xml24
-rw-r--r--java/com/android/dialer/calllog/ui/res/values/dimens.xml28
-rw-r--r--java/com/android/dialer/calllog/ui/res/values/strings.xml32
-rw-r--r--java/com/android/dialer/calllog/ui/res/values/styles.xml28
115 files changed, 4472 insertions, 341 deletions
diff --git a/java/com/android/dialer/calllog/CallLogComponent.java b/java/com/android/dialer/calllog/CallLogComponent.java
index 5cdd2b4d0..c7db2a1b8 100644
--- a/java/com/android/dialer/calllog/CallLogComponent.java
+++ b/java/com/android/dialer/calllog/CallLogComponent.java
@@ -25,6 +25,8 @@ public abstract class CallLogComponent {
public abstract CallLogFramework callLogFramework();
+ public abstract RefreshAnnotatedCallLogWorker getRefreshAnnotatedCallLogWorker();
+
public static CallLogComponent get(Context context) {
return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component())
.callLogComponent();
diff --git a/java/com/android/dialer/calllog/CallLogFramework.java b/java/com/android/dialer/calllog/CallLogFramework.java
index 508413b14..788e56b93 100644
--- a/java/com/android/dialer/calllog/CallLogFramework.java
+++ b/java/com/android/dialer/calllog/CallLogFramework.java
@@ -21,9 +21,10 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
+import com.android.dialer.buildtype.BuildType;
import com.android.dialer.calllog.datasources.CallLogDataSource;
+import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.common.Assert;
-import com.android.dialer.common.ConfigProviderBindings;
import com.android.dialer.common.LogUtil;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -38,7 +39,6 @@ import javax.inject.Singleton;
public final class CallLogFramework implements CallLogDataSource.ContentObserverCallbacks {
static final String PREF_FORCE_REBUILD = "callLogFrameworkForceRebuild";
- static final String PREF_LAST_REBUILD_TIMESTAMP_MILLIS = "callLogFrameworkLastRebuild";
private final DataSources dataSources;
@@ -49,20 +49,20 @@ public final class CallLogFramework implements CallLogDataSource.ContentObserver
this.dataSources = dataSources;
}
- public boolean isNewCallLogEnabled(Context context) {
- return ConfigProviderBindings.get(context).getBoolean("enable_new_call_log_tab", false);
- }
-
/** Registers the content observers for all data sources. */
public void registerContentObservers(Context appContext) {
LogUtil.enterBlock("CallLogFramework.registerContentObservers");
- if (!isNewCallLogEnabled(appContext)) {
- return;
- }
-
- for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) {
- dataSource.registerContentObservers(appContext, this);
+ // This is the same condition used in MainImpl#isNewUiEnabled. It means that bugfood/debug
+ // users will have "new call log" content observers firing. These observers usually do simple
+ // things like writing shared preferences.
+ // TODO(zachh): Find a way to access Main#isNewUiEnabled without creating a circular dependency.
+ if (BuildType.get() == BuildType.BUGFOOD || LogUtil.isDebugEnabled()) {
+ for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) {
+ dataSource.registerContentObservers(appContext, this);
+ }
+ } else {
+ LogUtil.i("CallLogFramework.registerContentObservers", "not registering content observers");
}
}
diff --git a/java/com/android/dialer/calllog/CallLogModule.java b/java/com/android/dialer/calllog/CallLogModule.java
index d7473a75e..2f2f16d5b 100644
--- a/java/com/android/dialer/calllog/CallLogModule.java
+++ b/java/com/android/dialer/calllog/CallLogModule.java
@@ -17,11 +17,9 @@
package com.android.dialer.calllog;
import com.android.dialer.calllog.datasources.CallLogDataSource;
+import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.calllog.datasources.contacts.ContactsDataSource;
import com.android.dialer.calllog.datasources.systemcalllog.SystemCallLogDataSource;
-import com.android.dialer.common.concurrent.DefaultDialerExecutorFactory;
-import com.android.dialer.common.concurrent.DialerExecutorFactory;
-import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import java.util.Arrays;
@@ -32,10 +30,6 @@ import java.util.List;
@Module
public abstract class CallLogModule {
- @Binds
- abstract DialerExecutorFactory bindDialerExecutorFactory(
- DefaultDialerExecutorFactory defaultDialerExecutorFactory);
-
@Provides
static DataSources provideCallLogDataSources(
SystemCallLogDataSource systemCallLogDataSource, ContactsDataSource contactsDataSource) {
diff --git a/java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java b/java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java
index f9f0c9935..273246649 100644
--- a/java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java
+++ b/java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java
@@ -18,91 +18,84 @@ package com.android.dialer.calllog;
import android.annotation.TargetApi;
import android.content.Context;
+import android.content.OperationApplicationException;
import android.content.SharedPreferences;
-import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
+import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.support.annotation.WorkerThread;
-import com.android.dialer.calllog.database.AnnotatedCallLog;
-import com.android.dialer.calllog.database.CallLogMutations;
+import com.android.dialer.calllog.database.CallLogDatabaseComponent;
import com.android.dialer.calllog.datasources.CallLogDataSource;
+import com.android.dialer.calllog.datasources.CallLogMutations;
+import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.inject.ApplicationContext;
import javax.inject.Inject;
/**
* Worker which brings the annotated call log up to date, if necessary.
*
- * <p>Accepts a boolean which indicates if the dirty check should be skipped, and returns true if
- * the annotated call log was updated.
+ * <p>Accepts a boolean which indicates if the dirty check should be skipped.
*/
-public class RefreshAnnotatedCallLogWorker implements Worker<Boolean, Boolean> {
+public class RefreshAnnotatedCallLogWorker implements Worker<Boolean, Void> {
private final Context appContext;
private final DataSources dataSources;
@Inject
- public RefreshAnnotatedCallLogWorker(Context appContext, DataSources dataSources) {
+ RefreshAnnotatedCallLogWorker(@ApplicationContext Context appContext, DataSources dataSources) {
this.appContext = appContext;
this.dataSources = dataSources;
}
@Override
- public Boolean doInBackground(Boolean skipDirtyCheck) {
- LogUtil.enterBlock("RefreshAnnotatedCallLogWorker.doInBackgroundFallible");
+ public Void doInBackground(Boolean skipDirtyCheck)
+ throws RemoteException, OperationApplicationException {
+ LogUtil.enterBlock("RefreshAnnotatedCallLogWorker.doInBackground");
long startTime = System.currentTimeMillis();
- boolean annotatedCallLogUpdated = checkDirtyAndRebuildIfNecessary(appContext, skipDirtyCheck);
+ checkDirtyAndRebuildIfNecessary(appContext, skipDirtyCheck);
LogUtil.i(
- "RefreshAnnotatedCallLogWorker.doInBackgroundFallible",
- "updated? %s, took %dms",
- annotatedCallLogUpdated,
+ "RefreshAnnotatedCallLogWorker.doInBackground",
+ "took %dms",
System.currentTimeMillis() - startTime);
- return annotatedCallLogUpdated;
+ return null;
}
@WorkerThread
- private boolean checkDirtyAndRebuildIfNecessary(Context appContext, boolean skipDirtyCheck) {
+ private void checkDirtyAndRebuildIfNecessary(Context appContext, boolean skipDirtyCheck)
+ throws RemoteException, OperationApplicationException {
Assert.isWorkerThread();
long startTime = System.currentTimeMillis();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext);
- long lastRebuildTimeMillis =
- sharedPreferences.getLong(CallLogFramework.PREF_LAST_REBUILD_TIMESTAMP_MILLIS, 0);
- if (lastRebuildTimeMillis == 0) {
- LogUtil.i(
- "RefreshAnnotatedCallLogWorker.checkDirtyAndRebuildIfNecessary",
- "annotated call log has never been built, marking it dirty");
- }
+ // Default to true. If the pref doesn't exist, the annotated call log hasn't been created and
+ // we just skip isDirty checks and force a rebuild.
boolean forceRebuildPrefValue =
- sharedPreferences.getBoolean(CallLogFramework.PREF_FORCE_REBUILD, false);
+ sharedPreferences.getBoolean(CallLogFramework.PREF_FORCE_REBUILD, true);
if (forceRebuildPrefValue) {
LogUtil.i(
"RefreshAnnotatedCallLogWorker.checkDirtyAndRebuildIfNecessary",
- "call log has been marked dirty");
+ "annotated call log has been marked dirty or does not exist");
}
- boolean isDirty =
- lastRebuildTimeMillis == 0
- || skipDirtyCheck
- || forceRebuildPrefValue
- || isDirty(appContext);
+ boolean isDirty = skipDirtyCheck || forceRebuildPrefValue || isDirty(appContext);
+
LogUtil.i(
"RefreshAnnotatedCallLogWorker.checkDirtyAndRebuildIfNecessary",
"isDirty took: %dms",
System.currentTimeMillis() - startTime);
if (isDirty) {
startTime = System.currentTimeMillis();
- rebuild(appContext, lastRebuildTimeMillis);
+ rebuild(appContext);
LogUtil.i(
"RefreshAnnotatedCallLogWorker.checkDirtyAndRebuildIfNecessary",
"rebuild took: %dms",
System.currentTimeMillis() - startTime);
- return true; // Annotated call log was updated.
}
- return false; // Annotated call log was not updated.
}
@WorkerThread
@@ -129,52 +122,58 @@ public class RefreshAnnotatedCallLogWorker implements Worker<Boolean, Boolean> {
@TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources
@WorkerThread
- private void rebuild(Context appContext, long lastRebuildTimeMillis) {
+ private void rebuild(Context appContext) throws RemoteException, OperationApplicationException {
Assert.isWorkerThread();
- // TODO: Start a transaction?
- try (SQLiteDatabase database = AnnotatedCallLog.getWritableDatabase(appContext)) {
+ CallLogMutations mutations = new CallLogMutations();
- CallLogMutations mutations = new CallLogMutations();
+ // System call log data source must go first!
+ CallLogDataSource systemCallLogDataSource = dataSources.getSystemCallLogDataSource();
+ String dataSourceName = getName(systemCallLogDataSource);
+ LogUtil.i("RefreshAnnotatedCallLogWorker.rebuild", "filling %s", dataSourceName);
+ long startTime = System.currentTimeMillis();
+ systemCallLogDataSource.fill(appContext, mutations);
+ LogUtil.i(
+ "RefreshAnnotatedCallLogWorker.rebuild",
+ "%s.fill took: %dms",
+ dataSourceName,
+ System.currentTimeMillis() - startTime);
- // System call log data source must go first!
- CallLogDataSource systemCallLogDataSource = dataSources.getSystemCallLogDataSource();
- String dataSourceName = getName(systemCallLogDataSource);
+ for (CallLogDataSource dataSource : dataSources.getDataSourcesExcludingSystemCallLog()) {
+ dataSourceName = getName(dataSource);
LogUtil.i("RefreshAnnotatedCallLogWorker.rebuild", "filling %s", dataSourceName);
- long startTime = System.currentTimeMillis();
- systemCallLogDataSource.fill(appContext, database, lastRebuildTimeMillis, mutations);
+ startTime = System.currentTimeMillis();
+ dataSource.fill(appContext, mutations);
LogUtil.i(
- "RefreshAnnotatedCallLogWorker.rebuild",
+ "CallLogFramework.rebuild",
"%s.fill took: %dms",
dataSourceName,
System.currentTimeMillis() - startTime);
+ }
+ LogUtil.i("RefreshAnnotatedCallLogWorker.rebuild", "applying mutations to database");
+ startTime = System.currentTimeMillis();
+ CallLogDatabaseComponent.get(appContext)
+ .mutationApplier()
+ .applyToDatabase(mutations, appContext);
+ LogUtil.i(
+ "RefreshAnnotatedCallLogWorker.rebuild",
+ "applyToDatabase took: %dms",
+ System.currentTimeMillis() - startTime);
- for (CallLogDataSource dataSource : dataSources.getDataSourcesExcludingSystemCallLog()) {
- dataSourceName = getName(dataSource);
- LogUtil.i("RefreshAnnotatedCallLogWorker.rebuild", "filling %s", dataSourceName);
- startTime = System.currentTimeMillis();
- dataSource.fill(appContext, database, lastRebuildTimeMillis, mutations);
- LogUtil.i(
- "CallLogFramework.rebuild",
- "%s.fill took: %dms",
- dataSourceName,
- System.currentTimeMillis() - startTime);
- }
- LogUtil.i("RefreshAnnotatedCallLogWorker.rebuild", "applying mutations to database");
+ for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) {
+ dataSourceName = getName(dataSource);
+ LogUtil.i("RefreshAnnotatedCallLogWorker.rebuild", "onSuccessfulFill'ing %s", dataSourceName);
startTime = System.currentTimeMillis();
- mutations.applyToDatabase(database);
+ dataSource.onSuccessfulFill(appContext);
LogUtil.i(
- "RefreshAnnotatedCallLogWorker.rebuild",
- "applyToDatabase took: %dms",
+ "CallLogFramework.rebuild",
+ "%s.onSuccessfulFill took: %dms",
+ dataSourceName,
System.currentTimeMillis() - startTime);
}
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext);
- sharedPreferences
- .edit()
- .putBoolean(CallLogFramework.PREF_FORCE_REBUILD, false)
- .putLong(CallLogFramework.PREF_LAST_REBUILD_TIMESTAMP_MILLIS, System.currentTimeMillis())
- .commit();
+ sharedPreferences.edit().putBoolean(CallLogFramework.PREF_FORCE_REBUILD, false).apply();
}
private static String getName(CallLogDataSource dataSource) {
diff --git a/java/com/android/dialer/calllog/database/AndroidManifest.xml b/java/com/android/dialer/calllog/database/AndroidManifest.xml
new file mode 100644
index 000000000..396a6d9a1
--- /dev/null
+++ b/java/com/android/dialer/calllog/database/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<!--
+ ~ 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
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.dialer.calllog.database">
+
+ <application>
+
+ <provider
+ android:authorities="com.android.dialer.annotatedcalllog"
+ android:exported="false"
+ android:multiprocess="false"
+ android:name=".AnnotatedCallLogContentProvider"/>
+
+ </application>
+</manifest>
diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLog.java b/java/com/android/dialer/calllog/database/AnnotatedCallLog.java
deleted file mode 100644
index 7dca44a60..000000000
--- a/java/com/android/dialer/calllog/database/AnnotatedCallLog.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.database;
-
-import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
-import android.support.annotation.WorkerThread;
-import com.android.dialer.common.Assert;
-
-/** Static methods and constants for interacting with the annotated call log table. */
-public final class AnnotatedCallLog {
-
- private static final String DATABASE_NAME = "annotated_call_log.db";
-
- public static final String TABLE_NAME = "AnnotatedCallLog";
-
- /** Column names for the annotated call log table. */
- public static final class Columns {
- public static final String ID = "_id";
- public static final String TIMESTAMP = "timestamp";
- public static final String CONTACT_NAME = "contact_name";
- }
-
- private AnnotatedCallLog() {}
-
- @WorkerThread
- public static SQLiteDatabase getWritableDatabase(Context appContext) {
- Assert.isWorkerThread();
-
- return new AnnotatedCallLogDatabaseHelper(appContext, DATABASE_NAME).getWritableDatabase();
- }
-
- @WorkerThread
- public static SQLiteDatabase getReadableDatabase(Context appContext) {
- Assert.isWorkerThread();
-
- return new AnnotatedCallLogDatabaseHelper(appContext, DATABASE_NAME).getReadableDatabase();
- }
-}
diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java
new file mode 100644
index 000000000..9a3d2e20f
--- /dev/null
+++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java
@@ -0,0 +1,333 @@
+/*
+ * 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.database;
+
+import android.annotation.TargetApi;
+import android.content.ContentProvider;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.OperationApplicationException;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+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.CoalescedAnnotatedCallLog;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import java.util.ArrayList;
+
+/** {@link ContentProvider} for the annotated call log. */
+public class AnnotatedCallLogContentProvider extends ContentProvider {
+
+ /**
+ * We sometimes run queries where we potentially pass every ID into a where clause using the
+ * (?,?,?,...) syntax. The maximum number of host parameters is 999, so that's the maximum size
+ * this table can be. See https://www.sqlite.org/limits.html for more details.
+ */
+ private static final int MAX_ROWS = 999;
+
+ 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 COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE = 3;
+
+ private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+ static {
+ uriMatcher.addURI(
+ AnnotatedCallLogContract.AUTHORITY, AnnotatedCallLog.TABLE, ANNOTATED_CALL_LOG_TABLE_CODE);
+ uriMatcher.addURI(
+ AnnotatedCallLogContract.AUTHORITY,
+ AnnotatedCallLog.TABLE + "/#",
+ ANNOTATED_CALL_LOG_TABLE_ID_CODE);
+ uriMatcher.addURI(
+ AnnotatedCallLogContract.AUTHORITY,
+ CoalescedAnnotatedCallLog.TABLE,
+ COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE);
+ }
+
+ private AnnotatedCallLogDatabaseHelper databaseHelper;
+ private Coalescer coalescer;
+
+ private final ThreadLocal<Boolean> applyingBatch = new ThreadLocal<>();
+
+ /** Ensures that only a single notification is generated from {@link #applyBatch(ArrayList)}. */
+ private boolean isApplyingBatch() {
+ return applyingBatch.get() != null && applyingBatch.get();
+ }
+
+ @Override
+ public boolean onCreate() {
+ databaseHelper = new AnnotatedCallLogDatabaseHelper(getContext(), MAX_ROWS);
+ coalescer = CallLogDatabaseComponent.get(getContext()).coalescer();
+ return true;
+ }
+
+ @TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources
+ @Nullable
+ @Override
+ public Cursor query(
+ @NonNull Uri uri,
+ @Nullable String[] projection,
+ @Nullable String selection,
+ @Nullable String[] selectionArgs,
+ @Nullable String sortOrder) {
+ SQLiteDatabase db = databaseHelper.getReadableDatabase();
+ SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
+ queryBuilder.setTables(AnnotatedCallLog.TABLE);
+ int match = uriMatcher.match(uri);
+ switch (match) {
+ case ANNOTATED_CALL_LOG_TABLE_ID_CODE:
+ queryBuilder.appendWhere(AnnotatedCallLog._ID + "=" + ContentUris.parseId(uri));
+ // fall through
+ case ANNOTATED_CALL_LOG_TABLE_CODE:
+ Cursor cursor =
+ queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
+ if (cursor != null) {
+ cursor.setNotificationUri(
+ getContext().getContentResolver(), AnnotatedCallLog.CONTENT_URI);
+ } else {
+ LogUtil.w("AnnotatedCallLogContentProvider.query", "cursor was null");
+ }
+ 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");
+ try (Cursor allAnnotatedCallLogRows =
+ queryBuilder.query(
+ db, null, null, null, null, null, AnnotatedCallLog.TIMESTAMP + " DESC")) {
+ Cursor coalescedRows = coalescer.coalesce(allAnnotatedCallLogRows);
+ coalescedRows.setNotificationUri(
+ getContext().getContentResolver(), CoalescedAnnotatedCallLog.CONTENT_URI);
+ return coalescedRows;
+ }
+ default:
+ throw new IllegalArgumentException("Unknown uri: " + uri);
+ }
+ }
+
+ @Nullable
+ @Override
+ public String getType(@NonNull Uri uri) {
+ return AnnotatedCallLog.CONTENT_ITEM_TYPE;
+ }
+
+ @Nullable
+ @Override
+ public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+ // Javadoc states values is not nullable, even though it is annotated as such (b/38123194)!
+ Assert.checkArgument(values != null);
+
+ SQLiteDatabase database = databaseHelper.getWritableDatabase();
+ int match = uriMatcher.match(uri);
+ switch (match) {
+ case ANNOTATED_CALL_LOG_TABLE_CODE:
+ Assert.checkArgument(
+ values.get(AnnotatedCallLog._ID) != null, "You must specify an _ID when inserting");
+ break;
+ case ANNOTATED_CALL_LOG_TABLE_ID_CODE:
+ Long idFromUri = ContentUris.parseId(uri);
+ Long idFromValues = values.getAsLong(AnnotatedCallLog._ID);
+ Assert.checkArgument(
+ idFromValues == null || idFromValues.equals(idFromUri),
+ "_ID from values %d does not match ID from URI: %s",
+ idFromValues,
+ uri);
+ if (idFromValues == null) {
+ values.put(AnnotatedCallLog._ID, idFromUri);
+ }
+ break;
+ case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE:
+ throw new UnsupportedOperationException("coalesced call log does not support inserting");
+ default:
+ throw new IllegalArgumentException("Unknown uri: " + uri);
+ }
+ long id = database.insert(AnnotatedCallLog.TABLE, null, values);
+ if (id < 0) {
+ LogUtil.w(
+ "AnnotatedCallLogContentProvider.insert",
+ "error inserting row with id: %d",
+ values.get(AnnotatedCallLog._ID));
+ return null;
+ }
+ Uri insertedUri = ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id);
+ if (!isApplyingBatch()) {
+ notifyChange(insertedUri);
+ }
+ return insertedUri;
+ }
+
+ @Override
+ public int delete(
+ @NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
+ SQLiteDatabase database = databaseHelper.getWritableDatabase();
+ final int match = uriMatcher.match(uri);
+ switch (match) {
+ case ANNOTATED_CALL_LOG_TABLE_CODE:
+ break;
+ case ANNOTATED_CALL_LOG_TABLE_ID_CODE:
+ Assert.checkArgument(selection == null, "Do not specify selection when deleting by ID");
+ Assert.checkArgument(
+ selectionArgs == null, "Do not specify selection args when deleting by ID");
+ long id = ContentUris.parseId(uri);
+ Assert.checkArgument(id != -1, "error parsing id from uri %s", uri);
+ selection = getSelectionWithId(id);
+ break;
+ case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE:
+ throw new UnsupportedOperationException("coalesced call log does not support deleting");
+ default:
+ throw new IllegalArgumentException("Unknown uri: " + uri);
+ }
+ int rows = database.delete(AnnotatedCallLog.TABLE, selection, selectionArgs);
+ if (rows > 0) {
+ if (!isApplyingBatch()) {
+ notifyChange(uri);
+ }
+ } else {
+ LogUtil.w("AnnotatedCallLogContentProvider.delete", "no rows deleted");
+ }
+ return rows;
+ }
+
+ @Override
+ public int update(
+ @NonNull Uri uri,
+ @Nullable ContentValues values,
+ @Nullable String selection,
+ @Nullable String[] selectionArgs) {
+ // Javadoc states values is not nullable, even though it is annotated as such (b/38123194)!
+ Assert.checkArgument(values != null);
+
+ SQLiteDatabase database = databaseHelper.getWritableDatabase();
+ int match = uriMatcher.match(uri);
+ switch (match) {
+ case ANNOTATED_CALL_LOG_TABLE_CODE:
+ break;
+ case ANNOTATED_CALL_LOG_TABLE_ID_CODE:
+ Assert.checkArgument(
+ !values.containsKey(AnnotatedCallLog._ID), "Do not specify _ID when updating by ID");
+ Assert.checkArgument(selection == null, "Do not specify selection when updating by ID");
+ Assert.checkArgument(
+ selectionArgs == null, "Do not specify selection args when updating by ID");
+ selection = getSelectionWithId(ContentUris.parseId(uri));
+ break;
+ case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE:
+ throw new UnsupportedOperationException("coalesced call log does not support updating");
+ default:
+ throw new IllegalArgumentException("Unknown uri: " + uri);
+ }
+ int rows = database.update(AnnotatedCallLog.TABLE, values, selection, selectionArgs);
+ if (rows > 0) {
+ if (!isApplyingBatch()) {
+ notifyChange(uri);
+ }
+ } else {
+ LogUtil.w("AnnotatedCallLogContentProvider.update", "no rows updated");
+ }
+ return rows;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Note: When applyBatch is used with the AnnotatedCallLog, only a single notification for the
+ * content URI is generated, not individual notifications for each affected URI.
+ */
+ @NonNull
+ @Override
+ public ContentProviderResult[] applyBatch(@NonNull ArrayList<ContentProviderOperation> operations)
+ throws OperationApplicationException {
+ ContentProviderResult[] results = new ContentProviderResult[operations.size()];
+ if (operations.isEmpty()) {
+ return results;
+ }
+
+ SQLiteDatabase database = databaseHelper.getWritableDatabase();
+ try {
+ applyingBatch.set(true);
+ database.beginTransaction();
+ for (int i = 0; i < operations.size(); i++) {
+ ContentProviderOperation operation = operations.get(i);
+ int match = uriMatcher.match(operation.getUri());
+ switch (match) {
+ case ANNOTATED_CALL_LOG_TABLE_CODE:
+ case ANNOTATED_CALL_LOG_TABLE_ID_CODE:
+ // These are allowed values, continue.
+ break;
+ case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE:
+ throw new UnsupportedOperationException(
+ "coalesced call log does not support applyBatch");
+ default:
+ throw new IllegalArgumentException("Unknown uri: " + operation.getUri());
+ }
+ ContentProviderResult result = operation.apply(this, results, i);
+ if (operations.get(i).isInsert()) {
+ if (result.uri == null) {
+ throw new OperationApplicationException("error inserting row");
+ }
+ } else if (result.count == 0) {
+ /*
+ * The batches built by MutationApplier happen to contain operations in order of:
+ *
+ * 1. Inserts
+ * 2. Updates
+ * 3. Deletes
+ *
+ * Let's say the last row in the table is row Z, and MutationApplier wishes to update it,
+ * as well as insert row A. When row A gets inserted, row Z will be deleted via the
+ * trigger if the table is full. Then later, when we try to process the update for row Z,
+ * it won't exist.
+ */
+ LogUtil.w(
+ "AnnotatedCallLogContentProvider.applyBatch",
+ "update or delete failed, possibly because row got cleaned up");
+ }
+ results[i] = result;
+ }
+ database.setTransactionSuccessful();
+ } finally {
+ applyingBatch.set(false);
+ database.endTransaction();
+ }
+ notifyChange(AnnotatedCallLog.CONTENT_URI);
+ return results;
+ }
+
+ private String getSelectionWithId(long id) {
+ return AnnotatedCallLog._ID + "=" + id;
+ }
+
+ private void notifyChange(Uri uri) {
+ getContext().getContentResolver().notifyChange(uri, 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);
+ }
+}
diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
index 7b28e5505..e1ec0f6b1 100644
--- a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
+++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
@@ -16,37 +16,75 @@
package com.android.dialer.calllog.database;
-import static com.android.dialer.calllog.database.AnnotatedCallLog.Columns.CONTACT_NAME;
-import static com.android.dialer.calllog.database.AnnotatedCallLog.Columns.ID;
-import static com.android.dialer.calllog.database.AnnotatedCallLog.Columns.TIMESTAMP;
-
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.common.LogUtil;
+import java.util.Locale;
/** {@link SQLiteOpenHelper} for the AnnotatedCallLog database. */
class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper {
+ private final int maxRows;
- AnnotatedCallLogDatabaseHelper(Context appContext, String databaseName) {
- super(appContext, databaseName, null, 1);
+ AnnotatedCallLogDatabaseHelper(Context appContext, int maxRows) {
+ super(appContext, "annotated_call_log.db", null, 1);
+ this.maxRows = maxRows;
}
- private static final String CREATE_SQL =
+ private static final String CREATE_TABLE_SQL =
new StringBuilder()
- .append("create table if not exists " + AnnotatedCallLog.TABLE_NAME + " (")
- .append(ID + " integer primary key, ")
- .append(TIMESTAMP + " integer, ")
- .append(CONTACT_NAME + " string")
+ .append("create table if not exists " + AnnotatedCallLog.TABLE + " (")
+ // Common columns.
+ .append(AnnotatedCallLog._ID + " integer primary key, ")
+ .append(AnnotatedCallLog.TIMESTAMP + " integer, ")
+ .append(AnnotatedCallLog.NAME + " string, ")
+ .append(AnnotatedCallLog.FORMATTED_NUMBER + " string, ")
+ .append(AnnotatedCallLog.PHOTO_URI + " string, ")
+ .append(AnnotatedCallLog.PHOTO_ID + " integer, ")
+ .append(AnnotatedCallLog.LOOKUP_URI + " string, ")
+ .append(AnnotatedCallLog.NUMBER_TYPE_LABEL + " string, ")
+ .append(AnnotatedCallLog.IS_READ + " integer, ")
+ .append(AnnotatedCallLog.NEW + " integer, ")
+ .append(AnnotatedCallLog.GEOCODED_LOCATION + " string, ")
+ .append(AnnotatedCallLog.PHONE_ACCOUNT_LABEL + " string, ")
+ .append(AnnotatedCallLog.PHONE_ACCOUNT_COLOR + " integer, ")
+ .append(AnnotatedCallLog.FEATURES + " integer, ")
+ .append(AnnotatedCallLog.IS_BUSINESS + " integer, ")
+ .append(AnnotatedCallLog.IS_VOICEMAIL + " integer, ")
+ // Columns only in AnnotatedCallLog
+ .append(AnnotatedCallLog.NUMBER + " blob, ")
+ .append(AnnotatedCallLog.TYPE + " integer")
.append(");")
.toString();
+ /** Deletes all but the first maxRows rows (by timestamp) to keep the table a manageable size. */
+ private static final String CREATE_TRIGGER_SQL =
+ "create trigger delete_old_rows after insert on "
+ + AnnotatedCallLog.TABLE
+ + " when (select count(*) from "
+ + AnnotatedCallLog.TABLE
+ + ") > %d"
+ + " begin delete from "
+ + AnnotatedCallLog.TABLE
+ + " where "
+ + AnnotatedCallLog._ID
+ + " in (select "
+ + AnnotatedCallLog._ID
+ + " from "
+ + AnnotatedCallLog.TABLE
+ + " order by timestamp limit (select count(*)-%d"
+ + " from "
+ + AnnotatedCallLog.TABLE
+ + " )); end;";
+
@Override
public void onCreate(SQLiteDatabase db) {
LogUtil.enterBlock("AnnotatedCallLogDatabaseHelper.onCreate");
long startTime = System.currentTimeMillis();
- db.execSQL(CREATE_SQL);
- // TODO: Consider logging impression.
+ db.execSQL(CREATE_TABLE_SQL);
+ db.execSQL(String.format(Locale.US, CREATE_TRIGGER_SQL, maxRows, maxRows));
+ // TODO(zachh): Consider logging impression.
LogUtil.i(
"AnnotatedCallLogDatabaseHelper.onCreate",
"took: %dms",
diff --git a/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java b/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java
new file mode 100644
index 000000000..ede46911c
--- /dev/null
+++ b/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java
@@ -0,0 +1,40 @@
+/*
+ * 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.database;
+
+import android.content.Context;
+import com.android.dialer.inject.HasRootComponent;
+import dagger.Subcomponent;
+
+/** Dagger component for database package. */
+@Subcomponent
+public abstract class CallLogDatabaseComponent {
+
+ public abstract Coalescer coalescer();
+
+ public abstract MutationApplier mutationApplier();
+
+ public static CallLogDatabaseComponent get(Context context) {
+ return ((CallLogDatabaseComponent.HasComponent)
+ ((HasRootComponent) context.getApplicationContext()).component())
+ .callLogDatabaseComponent();
+ }
+
+ /** Used to refer to the root application component. */
+ public interface HasComponent {
+ CallLogDatabaseComponent callLogDatabaseComponent();
+ }
+}
diff --git a/java/com/android/dialer/calllog/database/CallLogMutations.java b/java/com/android/dialer/calllog/database/CallLogMutations.java
deleted file mode 100644
index ec020c6af..000000000
--- a/java/com/android/dialer/calllog/database/CallLogMutations.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.database;
-
-import android.content.ContentValues;
-import android.database.sqlite.SQLiteDatabase;
-import android.support.annotation.WorkerThread;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import com.android.dialer.common.Assert;
-
-/** A collection of mutations to the annotated call log. */
-public final class CallLogMutations {
-
- private final ArrayMap<Integer, ContentValues> inserts = new ArrayMap<>();
- private final ArrayMap<Integer, ContentValues> updates = new ArrayMap<>();
- private final ArraySet<Integer> deletes = new ArraySet<>();
-
- /** @param contentValues an entire row not including the ID */
- public void insert(int id, ContentValues contentValues) {
- inserts.put(id, contentValues);
- }
-
- /** @param contentValues the specific columns to update, not including the ID. */
- public void update(int id, ContentValues contentValues) {
- // TODO: Consider merging automatically.
- updates.put(id, contentValues);
- }
-
- public void delete(int id) {
- deletes.add(id);
- }
-
- public boolean isEmpty() {
- return inserts.isEmpty() && updates.isEmpty() && deletes.isEmpty();
- }
-
- @WorkerThread
- public void applyToDatabase(SQLiteDatabase writableDatabase) {
- Assert.isWorkerThread();
-
- // TODO: Implementation.
- }
-}
diff --git a/java/com/android/dialer/calllog/database/Coalescer.java b/java/com/android/dialer/calllog/database/Coalescer.java
new file mode 100644
index 000000000..63fa9f828
--- /dev/null
+++ b/java/com/android/dialer/calllog/database/Coalescer.java
@@ -0,0 +1,194 @@
+/*
+ * 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.database;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.support.annotation.NonNull;
+import android.support.annotation.WorkerThread;
+import com.android.dialer.DialerPhoneNumber;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
+import com.android.dialer.calllog.datasources.CallLogDataSource;
+import com.android.dialer.calllog.datasources.DataSources;
+import com.android.dialer.common.Assert;
+import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.protobuf.InvalidProtocolBufferException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import javax.inject.Inject;
+
+/**
+ * Coalesces call log rows by combining some adjacent rows.
+ *
+ * <p>Applies the business which logic which determines which adjacent rows should be coalasced, and
+ * then delegates to each data source to determine how individual columns should be aggregated.
+ */
+public class Coalescer {
+
+ private final DataSources dataSources;
+
+ @Inject
+ Coalescer(DataSources dataSources) {
+ this.dataSources = dataSources;
+ }
+
+ /**
+ * Reads the entire {@link AnnotatedCallLog} database into memory from the provided {@code
+ * allAnnotatedCallLog} parameter and then builds and returns a new {@link MatrixCursor} which is
+ * the result of combining adjacent rows which should be collapsed for display purposes.
+ *
+ * @param allAnnotatedCallLogRowsSortedByTimestampDesc all {@link AnnotatedCallLog} rows, sorted
+ * by timestamp descending
+ * @return a new {@link MatrixCursor} containing the {@link CoalescedAnnotatedCallLog} rows to
+ * display
+ */
+ @WorkerThread
+ @NonNull
+ Cursor coalesce(@NonNull Cursor allAnnotatedCallLogRowsSortedByTimestampDesc) {
+ Assert.isWorkerThread();
+
+ // Note: This method relies on rowsShouldBeCombined to determine which rows should be combined,
+ // but delegates to data sources to actually aggregate column values.
+
+ DialerPhoneNumberUtil dialerPhoneNumberUtil =
+ new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance());
+
+ MatrixCursor allCoalescedRowsMatrixCursor =
+ new MatrixCursor(
+ CoalescedAnnotatedCallLog.ALL_COLUMNS,
+ Assert.isNotNull(allAnnotatedCallLogRowsSortedByTimestampDesc).getCount());
+
+ if (allAnnotatedCallLogRowsSortedByTimestampDesc.moveToFirst()) {
+ int coalescedRowId = 0;
+
+ List<ContentValues> currentRowGroup = new ArrayList<>();
+
+ do {
+ ContentValues currentRow =
+ cursorRowToContentValues(allAnnotatedCallLogRowsSortedByTimestampDesc);
+
+ if (currentRowGroup.isEmpty()) {
+ currentRowGroup.add(currentRow);
+ continue;
+ }
+
+ ContentValues previousRow = currentRowGroup.get(currentRowGroup.size() - 1);
+
+ if (!rowsShouldBeCombined(dialerPhoneNumberUtil, previousRow, currentRow)) {
+ ContentValues coalescedRow = coalesceRowsForAllDataSources(currentRowGroup);
+ coalescedRow.put(CoalescedAnnotatedCallLog.NUMBER_CALLS, currentRowGroup.size());
+ addContentValuesToMatrixCursor(
+ coalescedRow, allCoalescedRowsMatrixCursor, coalescedRowId++);
+ currentRowGroup.clear();
+ }
+ currentRowGroup.add(currentRow);
+ } while (allAnnotatedCallLogRowsSortedByTimestampDesc.moveToNext());
+
+ // Deal with leftover rows.
+ ContentValues coalescedRow = coalesceRowsForAllDataSources(currentRowGroup);
+ coalescedRow.put(CoalescedAnnotatedCallLog.NUMBER_CALLS, currentRowGroup.size());
+ addContentValuesToMatrixCursor(coalescedRow, allCoalescedRowsMatrixCursor, coalescedRowId);
+ }
+ return allCoalescedRowsMatrixCursor;
+ }
+
+ private static ContentValues cursorRowToContentValues(Cursor cursor) {
+ ContentValues values = new ContentValues();
+ String[] columns = cursor.getColumnNames();
+ int length = columns.length;
+ for (int i = 0; i < length; i++) {
+ if (cursor.getType(i) == Cursor.FIELD_TYPE_BLOB) {
+ values.put(columns[i], cursor.getBlob(i));
+ } else {
+ values.put(columns[i], cursor.getString(i));
+ }
+ }
+ return values;
+ }
+
+ /**
+ * @param row1 a row from {@link AnnotatedCallLog}
+ * @param row2 a row from {@link AnnotatedCallLog}
+ */
+ private static boolean rowsShouldBeCombined(
+ DialerPhoneNumberUtil dialerPhoneNumberUtil, ContentValues row1, ContentValues row2) {
+ // Don't combine rows which don't use the same phone account.
+ if (!Objects.equals(
+ row1.getAsString(AnnotatedCallLog.PHONE_ACCOUNT_LABEL),
+ row2.getAsString(AnnotatedCallLog.PHONE_ACCOUNT_LABEL))) {
+ return false;
+ }
+ DialerPhoneNumber number1;
+ DialerPhoneNumber number2;
+ try {
+ byte[] number1Bytes = row1.getAsByteArray(AnnotatedCallLog.NUMBER);
+ byte[] number2Bytes = row2.getAsByteArray(AnnotatedCallLog.NUMBER);
+
+ if (number1Bytes == null || number2Bytes == null) {
+ // Empty numbers should not be combined.
+ return false;
+ }
+
+ number1 = DialerPhoneNumber.parseFrom(number1Bytes);
+ number2 = DialerPhoneNumber.parseFrom(number2Bytes);
+ } catch (InvalidProtocolBufferException e) {
+ throw Assert.createAssertionFailException("error parsing DialerPhoneNumber proto", e);
+ }
+
+ if (!number1.hasDialerInternalPhoneNumber() && !number2.hasDialerInternalPhoneNumber()) {
+ // Empty numbers should not be combined.
+ return false;
+ }
+
+ if (!number1.hasDialerInternalPhoneNumber() || !number2.hasDialerInternalPhoneNumber()) {
+ // An empty number should not be combined with a non-empty number.
+ return false;
+ }
+ return dialerPhoneNumberUtil.isExactMatch(number1, number2);
+ }
+
+ /**
+ * Delegates to data sources to aggregate individual columns to create a new coalesced row.
+ *
+ * @param individualRows {@link AnnotatedCallLog} rows sorted by timestamp descending
+ * @return a {@link CoalescedAnnotatedCallLog} row
+ */
+ private ContentValues coalesceRowsForAllDataSources(List<ContentValues> individualRows) {
+ ContentValues coalescedValues = new ContentValues();
+ for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) {
+ coalescedValues.putAll(dataSource.coalesce(individualRows));
+ }
+ return coalescedValues;
+ }
+
+ /**
+ * @param contentValues a {@link CoalescedAnnotatedCallLog} row
+ * @param matrixCursor represents {@link CoalescedAnnotatedCallLog}
+ */
+ private static void addContentValuesToMatrixCursor(
+ ContentValues contentValues, MatrixCursor matrixCursor, int rowId) {
+ MatrixCursor.RowBuilder rowBuilder = matrixCursor.newRow();
+ rowBuilder.add(CoalescedAnnotatedCallLog._ID, rowId);
+ for (Map.Entry<String, Object> entry : contentValues.valueSet()) {
+ rowBuilder.add(entry.getKey(), entry.getValue());
+ }
+ }
+}
diff --git a/java/com/android/dialer/calllog/database/MutationApplier.java b/java/com/android/dialer/calllog/database/MutationApplier.java
new file mode 100644
index 000000000..21c8a507d
--- /dev/null
+++ b/java/com/android/dialer/calllog/database/MutationApplier.java
@@ -0,0 +1,105 @@
+/*
+ * 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.database;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.OperationApplicationException;
+import android.os.RemoteException;
+import android.support.annotation.WorkerThread;
+import android.text.TextUtils;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
+import com.android.dialer.calllog.datasources.CallLogMutations;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map.Entry;
+import javax.inject.Inject;
+
+/** Applies {@link CallLogMutations} to the annotated call log. */
+public class MutationApplier {
+
+ @Inject
+ MutationApplier() {}
+
+ /** Applies the provided {@link CallLogMutations} to the annotated call log. */
+ @WorkerThread
+ public void applyToDatabase(CallLogMutations mutations, Context appContext)
+ throws RemoteException, OperationApplicationException {
+ Assert.isWorkerThread();
+
+ if (mutations.isEmpty()) {
+ return;
+ }
+
+ ArrayList<ContentProviderOperation> operations = new ArrayList<>();
+
+ if (!mutations.getInserts().isEmpty()) {
+ LogUtil.i(
+ "CallLogMutations.applyToDatabase", "inserting %d rows", mutations.getInserts().size());
+ for (Entry<Long, ContentValues> entry : mutations.getInserts().entrySet()) {
+ long id = entry.getKey();
+ ContentValues contentValues = entry.getValue();
+ operations.add(
+ ContentProviderOperation.newInsert(
+ ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id))
+ .withValues(contentValues)
+ .build());
+ }
+ }
+
+ if (!mutations.getUpdates().isEmpty()) {
+ LogUtil.i(
+ "CallLogMutations.applyToDatabase", "updating %d rows", mutations.getUpdates().size());
+ for (Entry<Long, ContentValues> entry : mutations.getUpdates().entrySet()) {
+ long id = entry.getKey();
+ ContentValues contentValues = entry.getValue();
+ operations.add(
+ ContentProviderOperation.newUpdate(
+ ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id))
+ .withValues(contentValues)
+ .build());
+ }
+ }
+
+ if (!mutations.getDeletes().isEmpty()) {
+ LogUtil.i(
+ "CallLogMutations.applyToDatabase", "deleting %d rows", mutations.getDeletes().size());
+ String[] questionMarks = new String[mutations.getDeletes().size()];
+ Arrays.fill(questionMarks, "?");
+
+ String whereClause =
+ (AnnotatedCallLog._ID + " in (") + TextUtils.join(",", questionMarks) + ")";
+
+ String[] whereArgs = new String[mutations.getDeletes().size()];
+ int i = 0;
+ for (long id : mutations.getDeletes()) {
+ whereArgs[i++] = String.valueOf(id);
+ }
+
+ operations.add(
+ ContentProviderOperation.newDelete(AnnotatedCallLog.CONTENT_URI)
+ .withSelection(whereClause, whereArgs)
+ .build());
+ }
+
+ appContext.getContentResolver().applyBatch(AnnotatedCallLogContract.AUTHORITY, operations);
+ }
+}
diff --git a/java/com/android/dialer/calllog/database/annotated_call_log.proto b/java/com/android/dialer/calllog/database/annotated_call_log.proto
new file mode 100644
index 000000000..de2bc5f14
--- /dev/null
+++ b/java/com/android/dialer/calllog/database/annotated_call_log.proto
@@ -0,0 +1,15 @@
+syntax = "proto2";
+
+option java_package = "com.android.dialer";
+option java_multiple_files = true;
+option optimize_for = LITE_RUNTIME;
+
+// DIALER_SCRUB.UNCOMMENT_IN_OPEN_SOURCE option optimize_for = LITE_RUNTIME;
+
+package com.android.dialer;
+
+// A list of android.provider.CallLog.Calls.TYPE values ordered from newest to
+// oldest.
+message CallTypes {
+ repeated int32 type = 1;
+}
diff --git a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
new file mode 100644
index 000000000..25950f6b9
--- /dev/null
+++ b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
@@ -0,0 +1,259 @@
+/*
+ * 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.database.contract;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+import com.android.dialer.constants.Constants;
+import java.util.Arrays;
+
+/** Contract for the AnnotatedCallLog content provider. */
+public class AnnotatedCallLogContract {
+ public static final String AUTHORITY = Constants.get().getAnnotatedCallLogProviderAuthority();
+
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
+
+ /**
+ * Columns shared by {@link AnnotatedCallLog} and {@link CoalescedAnnotatedCallLog}.
+ *
+ * <p>When adding columns be sure to update {@link #ALL_COMMON_COLUMNS}.
+ */
+ interface CommonColumns extends BaseColumns {
+
+ /**
+ * Timestamp of the entry, in milliseconds.
+ *
+ * <p>Type: INTEGER (long)
+ */
+ String TIMESTAMP = "timestamp";
+
+ /**
+ * Copied from {@link android.provider.CallLog.Calls#CACHED_NAME}.
+ *
+ * <p>This is exactly how it should appear to the user. If the user's locale or name display
+ * preferences change, this column should be rewritten.
+ *
+ * <p>Type: TEXT
+ */
+ String NAME = "name";
+
+ /**
+ * Copied from {@link android.provider.CallLog.Calls#CACHED_FORMATTED_NUMBER}.
+ *
+ * <p>Type: TEXT
+ */
+ String FORMATTED_NUMBER = "formatted_number";
+
+ /**
+ * Copied from {@link android.provider.CallLog.Calls#CACHED_PHOTO_URI}.
+ *
+ * <p>TYPE: TEXT
+ */
+ String PHOTO_URI = "photo_uri";
+
+ /**
+ * Copied from {@link android.provider.CallLog.Calls#CACHED_PHOTO_ID}.
+ *
+ * <p>Type: INTEGER (long)
+ */
+ String PHOTO_ID = "photo_id";
+
+ /**
+ * Copied from {@link android.provider.CallLog.Calls#CACHED_LOOKUP_URI}.
+ *
+ * <p>TYPE: TEXT
+ */
+ String LOOKUP_URI = "lookup_uri";
+
+ // TODO(zachh): If we need to support photos other than local contacts', add a (blob?) column.
+
+ /**
+ * The number type as a string to be displayed to the user, for example "Home" or "Mobile".
+ *
+ * <p>This column should be updated for the appropriate language when the locale changes.
+ *
+ * <p>TYPE: TEXT
+ */
+ String NUMBER_TYPE_LABEL = "number_type_label";
+
+ /**
+ * See {@link android.provider.CallLog.Calls#IS_READ}.
+ *
+ * <p>TYPE: INTEGER (boolean)
+ */
+ String IS_READ = "is_read";
+
+ /**
+ * See {@link android.provider.CallLog.Calls#NEW}.
+ *
+ * <p>Type: INTEGER (boolean)
+ */
+ String NEW = "new";
+
+ /**
+ * See {@link android.provider.CallLog.Calls#GEOCODED_LOCATION}.
+ *
+ * <p>TYPE: TEXT
+ */
+ String GEOCODED_LOCATION = "geocoded_location";
+
+ /**
+ * String suitable for display which indicates the phone account used to make the call.
+ *
+ * <p>TYPE: TEXT
+ */
+ String PHONE_ACCOUNT_LABEL = "phone_account_label";
+
+ /**
+ * The color int for the phone account.
+ *
+ * <p>TYPE: INTEGER (int)
+ */
+ String PHONE_ACCOUNT_COLOR = "phone_account_color";
+
+ /**
+ * See {@link android.provider.CallLog.Calls#FEATURES}.
+ *
+ * <p>TYPE: INTEGER (int)
+ */
+ String FEATURES = "features";
+
+ /**
+ * True if a caller ID data source informed us that this is a business number. This is used to
+ * determine if a generic business avatar should be shown vs. a generic person avatar.
+ *
+ * <p>TYPE: INTEGER (boolean)
+ */
+ String IS_BUSINESS = "is_business";
+
+ /**
+ * True if this was a call to voicemail. This is used to determine if the voicemail avatar
+ * should be displayed.
+ *
+ * <p>TYPE: INTEGER (boolean)
+ */
+ String IS_VOICEMAIL = "is_voicemail";
+
+ String[] ALL_COMMON_COLUMNS =
+ new String[] {
+ _ID,
+ TIMESTAMP,
+ NAME,
+ FORMATTED_NUMBER,
+ PHOTO_URI,
+ PHOTO_ID,
+ LOOKUP_URI,
+ NUMBER_TYPE_LABEL,
+ IS_READ,
+ NEW,
+ GEOCODED_LOCATION,
+ PHONE_ACCOUNT_LABEL,
+ PHONE_ACCOUNT_COLOR,
+ FEATURES,
+ IS_BUSINESS,
+ IS_VOICEMAIL
+ };
+ }
+
+ /**
+ * AnnotatedCallLog table.
+ *
+ * <p>This contains all of the non-coalesced call log entries.
+ */
+ public static final class AnnotatedCallLog implements CommonColumns {
+
+ public static final String TABLE = "AnnotatedCallLog";
+
+ /** 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/annotated_call_log";
+
+ /**
+ * The phone number called or number the call came from, encoded as a {@link
+ * com.android.dialer.DialerPhoneNumber} proto. The number may be empty if it was an incoming
+ * call and the number was unknown.
+ *
+ * <p>This column is only present in the annotated call log, and not the coalesced annotated
+ * call log. The coalesced version uses a formatted number string rather than proto bytes.
+ *
+ * <p>Type: BLOB
+ */
+ public static final String NUMBER = "number";
+
+ /**
+ * Copied from {@link android.provider.CallLog.Calls#TYPE}.
+ *
+ * <p>Type: INTEGER (int)
+ */
+ public static final String TYPE = "type";
+ }
+
+ /**
+ * Coalesced view of the AnnotatedCallLog table.
+ *
+ * <p>This is an in-memory view of the {@link AnnotatedCallLog} with some adjacent entries
+ * collapsed.
+ *
+ * <p>When adding columns be sure to update {@link #COLUMNS_ONLY_IN_COALESCED_CALL_LOG}.
+ */
+ 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";
+
+ /**
+ * Number of AnnotatedCallLog rows represented by this CoalescedAnnotatedCallLog row.
+ *
+ * <p>Type: INTEGER
+ */
+ public static final String NUMBER_CALLS = "number_calls";
+
+ /**
+ * The call types of the most recent 3 calls, encoded as a CallTypes proto.
+ *
+ * <p>TYPE: BLOB
+ */
+ public static final String CALL_TYPES = "call_types";
+
+ /**
+ * Columns that are only in the {@link CoalescedAnnotatedCallLog} but not the {@link
+ * AnnotatedCallLog}.
+ */
+ private static final String[] COLUMNS_ONLY_IN_COALESCED_CALL_LOG =
+ new String[] {NUMBER_CALLS, CALL_TYPES};
+
+ /** All columns in the {@link CoalescedAnnotatedCallLog}. */
+ public static final String[] ALL_COLUMNS =
+ concat(ALL_COMMON_COLUMNS, COLUMNS_ONLY_IN_COALESCED_CALL_LOG);
+ }
+
+ private static String[] concat(String[] first, String[] second) {
+ String[] result = Arrays.copyOf(first, first.length + second.length);
+ System.arraycopy(second, 0, result, first.length, second.length);
+ return result;
+ }
+}
diff --git a/java/com/android/dialer/calllog/datasources/CallLogDataSource.java b/java/com/android/dialer/calllog/datasources/CallLogDataSource.java
index 13d0b842d..3fff3ba53 100644
--- a/java/com/android/dialer/calllog/datasources/CallLogDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/CallLogDataSource.java
@@ -16,13 +16,39 @@
package com.android.dialer.calllog.datasources;
+import android.content.ContentValues;
import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;
-import com.android.dialer.calllog.database.CallLogMutations;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract;
+import java.util.List;
-/** A source of data for one or more columns in the annotated call log. */
+/**
+ * A source of data for one or more columns in the annotated call log.
+ *
+ * <p>Data sources have three lifecycle operations, which are always called on the same thread and
+ * in the same order for a particular "checkDirtyAndRebuild" cycle. However, not all operations are
+ * always invoked.
+ *
+ * <ol>
+ * <li>{@link #isDirty(Context)}: Invoked only if the framework doesn't yet know if a rebuild is
+ * necessary.
+ * <li>{@link #fill(Context, CallLogMutations)}: Invoked only if the framework determined a
+ * rebuild is necessary.
+ * <li>{@link #onSuccessfulFill(Context)}: Invoked if and only if fill was previously called and
+ * the mutations provided by the previous fill operation succeeded in being applied.
+ * </ol>
+ *
+ * <p>Because {@link #isDirty(Context)} is not always invoked, {@link #fill(Context,
+ * CallLogMutations)} shouldn't rely on any state saved during {@link #isDirty(Context)}. It
+ * <em>is</em> safe to assume that {@link #onSuccessfulFill(Context)} refers to the previous fill
+ * operation.
+ *
+ * <p>The same data source objects may be reused across multiple checkDirtyAndRebuild cycles, so
+ * implementors should take care to clear any internal state at the start of a new cycle.
+ *
+ * <p>{@link #coalesce(List)} may be called from any worker thread at any time.
+ */
public interface CallLogDataSource {
/**
@@ -35,6 +61,8 @@ public interface CallLogDataSource {
* <p>Most implementations of this method will rely on some sort of last modified timestamp. If it
* is impossible for a data source to be modified without the dialer application being notified,
* this method may immediately return false.
+ *
+ * @see CallLogDataSource class doc for complete lifecyle information
*/
@WorkerThread
boolean isDirty(Context appContext);
@@ -43,16 +71,39 @@ public interface CallLogDataSource {
* Computes the set of mutations necessary to update the annotated call log with respect to this
* data source.
*
+ * @see CallLogDataSource class doc for complete lifecyle information
* @param mutations the set of mutations which this method should contribute to. Note that it may
* contain inserts from the system call log, and these inserts should be modified by each data
* source.
*/
@WorkerThread
- void fill(
- Context appContext,
- SQLiteDatabase readableDatabase,
- long lastRebuildTimeMillis,
- CallLogMutations mutations);
+ void fill(Context appContext, CallLogMutations mutations);
+
+ /**
+ * Called after database mutations have been applied to all data sources. This is useful for
+ * saving state such as the timestamp of the last row processed in an underlying database. Note
+ * that all mutations across all data sources are applied in a single transaction.
+ *
+ * @see CallLogDataSource class doc for complete lifecyle information
+ */
+ @WorkerThread
+ void onSuccessfulFill(Context appContext);
+
+ /**
+ * Combines raw annotated call log rows into a single coalesced row.
+ *
+ * <p>May be called by any worker thread at any time so implementations should take care to be
+ * threadsafe. (Ideally no state should be required to implement this.)
+ *
+ * @param individualRowsSortedByTimestampDesc group of fully populated rows from {@link
+ * AnnotatedCallLogContract.AnnotatedCallLog} which need to be combined for display purposes.
+ * This method should not modify this list.
+ * @return a partial {@link AnnotatedCallLogContract.CoalescedAnnotatedCallLog} row containing
+ * only columns which this data source is responsible for, which is the result of aggregating
+ * {@code individualRowsSortedByTimestampDesc}.
+ */
+ @WorkerThread
+ ContentValues coalesce(List<ContentValues> individualRowsSortedByTimestampDesc);
@MainThread
void registerContentObservers(
diff --git a/java/com/android/dialer/calllog/datasources/CallLogMutations.java b/java/com/android/dialer/calllog/datasources/CallLogMutations.java
new file mode 100644
index 000000000..148601d68
--- /dev/null
+++ b/java/com/android/dialer/calllog/datasources/CallLogMutations.java
@@ -0,0 +1,110 @@
+/*
+ * 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.datasources;
+
+import android.content.ContentValues;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import com.android.dialer.common.Assert;
+
+/** A collection of mutations to the annotated call log. */
+public final class CallLogMutations {
+
+ private final ArrayMap<Long, ContentValues> inserts = new ArrayMap<>();
+ private final ArrayMap<Long, ContentValues> updates = new ArrayMap<>();
+ private final ArraySet<Long> deletes = new ArraySet<>();
+
+ /**
+ * @param contentValues an entire row not including the ID
+ * @throws IllegalStateException if this {@link CallLogMutations} already contains an insert,
+ * update, or delete with the provided id
+ */
+ public void insert(long id, ContentValues contentValues) {
+ Assert.checkArgument(!inserts.containsKey(id), "Can't insert row already scheduled for insert");
+ Assert.checkArgument(!updates.containsKey(id), "Can't insert row scheduled for update");
+ Assert.checkArgument(!deletes.contains(id), "Can't insert row scheduled for delete");
+
+ inserts.put(id, contentValues);
+ }
+
+ /**
+ * Stores a database update using the provided ID and content values. If this {@link
+ * CallLogMutations} object already contains an update with the specified ID, the existing content
+ * values are merged with the provided ones, with the provided ones overwriting the existing ones
+ * for values with the same key.
+ *
+ * @param contentValues the specific columns to update, not including the ID.
+ * @throws IllegalStateException if this {@link CallLogMutations} already contains an insert or
+ * delete with the provided id
+ */
+ public void update(long id, ContentValues contentValues) {
+ Assert.checkArgument(!inserts.containsKey(id), "Can't update row scheduled for insert");
+ Assert.checkArgument(!deletes.contains(id), "Can't delete row scheduled for delete");
+
+ ContentValues existingContentValues = updates.get(id);
+ if (existingContentValues != null) {
+ existingContentValues.putAll(contentValues);
+ } else {
+ updates.put(id, contentValues);
+ }
+ }
+
+ /**
+ * @throws IllegalStateException if this {@link CallLogMutations} already contains an insert,
+ * update, or delete with the provided id
+ */
+ public void delete(long id) {
+ Assert.checkArgument(!inserts.containsKey(id), "Can't delete row scheduled for insert");
+ Assert.checkArgument(!updates.containsKey(id), "Can't delete row scheduled for update");
+ Assert.checkArgument(!deletes.contains(id), "Can't delete row already scheduled for delete");
+
+ deletes.add(id);
+ }
+
+ public boolean isEmpty() {
+ return inserts.isEmpty() && updates.isEmpty() && deletes.isEmpty();
+ }
+
+ /**
+ * Get the pending inserts.
+ *
+ * @return the pending inserts where the key is the annotated call log database ID and the values
+ * are values to be inserted (not including the ID)
+ */
+ public ArrayMap<Long, ContentValues> getInserts() {
+ return inserts;
+ }
+
+ /**
+ * Get the pending updates.
+ *
+ * @return the pending updates where the key is the annotated call log database ID and the values
+ * are values to be updated (not including the ID)
+ */
+ public ArrayMap<Long, ContentValues> getUpdates() {
+ return updates;
+ }
+
+ /**
+ * Get the pending deletes.
+ *
+ * @return the annotated call log database IDs corresponding to the rows to be deleted
+ */
+ public ArraySet<Long> getDeletes() {
+ return deletes;
+ }
+}
diff --git a/java/com/android/dialer/calllog/DataSources.java b/java/com/android/dialer/calllog/datasources/DataSources.java
index 21d190167..911ca3fa3 100644
--- a/java/com/android/dialer/calllog/DataSources.java
+++ b/java/com/android/dialer/calllog/datasources/DataSources.java
@@ -14,14 +14,13 @@
* limitations under the License
*/
-package com.android.dialer.calllog;
+package com.android.dialer.calllog.datasources;
-import com.android.dialer.calllog.datasources.CallLogDataSource;
import com.android.dialer.calllog.datasources.systemcalllog.SystemCallLogDataSource;
import java.util.List;
/** Immutable lists of data sources used to populate the annotated call log. */
-interface DataSources {
+public interface DataSources {
SystemCallLogDataSource getSystemCallLogDataSource();
diff --git a/java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java b/java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java
index 355940f6a..f0384b09a 100644
--- a/java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java
@@ -16,13 +16,14 @@
package com.android.dialer.calllog.datasources.contacts;
+import android.content.ContentValues;
import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;
-import com.android.dialer.calllog.database.CallLogMutations;
import com.android.dialer.calllog.datasources.CallLogDataSource;
+import com.android.dialer.calllog.datasources.CallLogMutations;
import com.android.dialer.common.Assert;
+import java.util.List;
import javax.inject.Inject;
/** Responsible for maintaining the contacts related columns in the annotated call log. */
@@ -36,7 +37,7 @@ public final class ContactsDataSource implements CallLogDataSource {
public boolean isDirty(Context appContext) {
Assert.isWorkerThread();
- // TODO: Implementation.
+ // TODO(zachh): Implementation.
return false;
}
@@ -44,17 +45,26 @@ public final class ContactsDataSource implements CallLogDataSource {
@Override
public void fill(
Context appContext,
- SQLiteDatabase readableDatabase,
- long lastRebuildTimeMillis,
CallLogMutations mutations) {
Assert.isWorkerThread();
- // TODO: Implementation.
+ // TODO(zachh): Implementation.
+ }
+
+ @Override
+ public void onSuccessfulFill(Context appContext) {
+ // TODO(zachh): Implementation.
+ }
+
+ @Override
+ public ContentValues coalesce(List<ContentValues> individualRowsSortedByTimestampDesc) {
+ // TODO(zachh): Implementation.
+ return new ContentValues();
}
@MainThread
@Override
public void registerContentObservers(
Context appContext, ContentObserverCallbacks contentObserverCallbacks) {
- // TODO: Guard against missing permissions during callback registration.
+ // TODO(zachh): Guard against missing permissions during callback registration.
}
}
diff --git a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
index ea6663fbe..1bdbb8a1b 100644
--- a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
@@ -16,28 +16,59 @@
package com.android.dialer.calllog.datasources.systemcalllog;
+import android.Manifest.permission;
+import android.annotation.TargetApi;
+import android.content.ContentValues;
import android.content.Context;
import android.database.ContentObserver;
-import android.database.sqlite.SQLiteDatabase;
+import android.database.Cursor;
import android.net.Uri;
+import android.os.Build;
import android.os.Handler;
+import android.preference.PreferenceManager;
import android.provider.CallLog;
+import android.provider.CallLog.Calls;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.support.annotation.ColorInt;
import android.support.annotation.MainThread;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
-import com.android.dialer.calllog.database.CallLogMutations;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import com.android.dialer.CallTypes;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
import com.android.dialer.calllog.datasources.CallLogDataSource;
+import com.android.dialer.calllog.datasources.CallLogMutations;
+import com.android.dialer.calllog.datasources.util.RowCombiner;
+import com.android.dialer.calllogutils.PhoneAccountUtils;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.ThreadUtil;
+import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
+import com.android.dialer.theme.R;
import com.android.dialer.util.PermissionsUtil;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
import javax.inject.Inject;
/**
* Responsible for defining the rows in the annotated call log and maintaining the columns in it
* which are derived from the system call log.
*/
+@SuppressWarnings("MissingPermission")
public class SystemCallLogDataSource implements CallLogDataSource {
+ @VisibleForTesting
+ static final String PREF_LAST_TIMESTAMP_PROCESSED = "systemCallLogLastTimestampProcessed";
+
+ @Nullable private Long lastTimestampProcessed;
+
@Inject
public SystemCallLogDataSource() {}
@@ -47,10 +78,13 @@ public class SystemCallLogDataSource implements CallLogDataSource {
Context appContext, ContentObserverCallbacks contentObserverCallbacks) {
Assert.isMainThread();
+ LogUtil.enterBlock("SystemCallLogDataSource.registerContentObservers");
+
if (!PermissionsUtil.hasCallLogReadPermissions(appContext)) {
LogUtil.i("SystemCallLogDataSource.registerContentObservers", "no call log permissions");
return;
}
+ // TODO(zachh): Need to somehow register observers if user enables permission after launch?
appContext
.getContentResolver()
@@ -71,23 +105,328 @@ public class SystemCallLogDataSource implements CallLogDataSource {
* column is unused). This means that we can't detect deletes without scanning the entire table,
* which would be too slow. So, we just rely on content observers to trigger rebuilds when any
* change is made to the system call log.
+ *
+ * Just return false unless the table has never been written to.
*/
- return false;
+ return !PreferenceManager.getDefaultSharedPreferences(appContext)
+ .contains(PREF_LAST_TIMESTAMP_PROCESSED);
}
@WorkerThread
@Override
- public void fill(
- Context appContext,
- SQLiteDatabase readableDatabase,
- long lastRebuildTimeMillis,
- CallLogMutations mutations) {
+ public void fill(Context appContext, CallLogMutations mutations) {
Assert.isWorkerThread();
+ lastTimestampProcessed = null;
+
+ if (!PermissionsUtil.hasPermission(appContext, permission.READ_CALL_LOG)) {
+ LogUtil.i("SystemCallLogDataSource.fill", "no call log permissions");
+ return;
+ }
+
// This data source should always run first so the mutations should always be empty.
- Assert.checkState(mutations.isEmpty());
+ Assert.checkArgument(mutations.isEmpty());
+
+ Set<Long> annotatedCallLogIds = getAnnotatedCallLogIds(appContext);
+
+ LogUtil.i(
+ "SystemCallLogDataSource.fill",
+ "found %d existing annotated call log ids",
+ annotatedCallLogIds.size());
+
+ handleInsertsAndUpdates(appContext, mutations, annotatedCallLogIds);
+ handleDeletes(appContext, annotatedCallLogIds, mutations);
+ }
+
+ @WorkerThread
+ @Override
+ public void onSuccessfulFill(Context appContext) {
+ // If a fill operation was a no-op, lastTimestampProcessed could still be null.
+ if (lastTimestampProcessed != null) {
+ PreferenceManager.getDefaultSharedPreferences(appContext)
+ .edit()
+ .putLong(PREF_LAST_TIMESTAMP_PROCESSED, lastTimestampProcessed)
+ .apply();
+ }
+ }
+
+ @Override
+ public ContentValues coalesce(List<ContentValues> individualRowsSortedByTimestampDesc) {
+ // TODO(zachh): Complete implementation.
+ ContentValues coalescedValues =
+ new RowCombiner(individualRowsSortedByTimestampDesc)
+ .useMostRecentLong(AnnotatedCallLog.TIMESTAMP)
+ .useMostRecentLong(AnnotatedCallLog.NEW)
+ .useMostRecentString(AnnotatedCallLog.NUMBER_TYPE_LABEL)
+ .useMostRecentString(AnnotatedCallLog.NAME)
+ .useMostRecentString(AnnotatedCallLog.FORMATTED_NUMBER)
+ .useMostRecentString(AnnotatedCallLog.PHOTO_URI)
+ .useMostRecentLong(AnnotatedCallLog.PHOTO_ID)
+ .useMostRecentString(AnnotatedCallLog.LOOKUP_URI)
+ .useMostRecentString(AnnotatedCallLog.GEOCODED_LOCATION)
+ .useSingleValueString(AnnotatedCallLog.PHONE_ACCOUNT_LABEL)
+ .useSingleValueLong(AnnotatedCallLog.PHONE_ACCOUNT_COLOR)
+ .combine();
+
+ CallTypes.Builder callTypes = CallTypes.newBuilder();
+ // Store a maximum of 3 call types since that's all we show to users via icons.
+ for (int i = 0; i < 3 && i < individualRowsSortedByTimestampDesc.size(); i++) {
+ callTypes.addType(
+ individualRowsSortedByTimestampDesc.get(i).getAsInteger(AnnotatedCallLog.TYPE));
+ }
+ coalescedValues.put(CoalescedAnnotatedCallLog.CALL_TYPES, callTypes.build().toByteArray());
+
+ return coalescedValues;
+ }
+
+ @TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources
+ private void handleInsertsAndUpdates(
+ Context appContext, CallLogMutations mutations, Set<Long> existingAnnotatedCallLogIds) {
+ long previousTimestampProcessed =
+ PreferenceManager.getDefaultSharedPreferences(appContext)
+ .getLong(PREF_LAST_TIMESTAMP_PROCESSED, 0L);
+
+ DialerPhoneNumberUtil dialerPhoneNumberUtil =
+ new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance());
+
+ // TODO(zachh): Really should be getting last 1000 by timestamp, not by last modified.
+ try (Cursor cursor =
+ appContext
+ .getContentResolver()
+ .query(
+ Calls.CONTENT_URI, // Excludes voicemail
+ new String[] {
+ Calls._ID,
+ Calls.DATE,
+ Calls.LAST_MODIFIED,
+ Calls.NUMBER,
+ Calls.TYPE,
+ Calls.COUNTRY_ISO,
+ Calls.CACHED_NAME,
+ Calls.CACHED_FORMATTED_NUMBER,
+ Calls.CACHED_PHOTO_URI,
+ Calls.CACHED_PHOTO_ID,
+ Calls.CACHED_LOOKUP_URI,
+ Calls.CACHED_NUMBER_TYPE,
+ Calls.CACHED_NUMBER_LABEL,
+ Calls.IS_READ,
+ Calls.NEW,
+ Calls.GEOCODED_LOCATION,
+ Calls.PHONE_ACCOUNT_COMPONENT_NAME,
+ Calls.PHONE_ACCOUNT_ID,
+ Calls.FEATURES
+ },
+ Calls.LAST_MODIFIED + " > ?",
+ new String[] {String.valueOf(previousTimestampProcessed)},
+ Calls.LAST_MODIFIED + " DESC LIMIT 1000")) {
+
+ if (cursor == null) {
+ LogUtil.e("SystemCallLogDataSource.handleInsertsAndUpdates", "null cursor");
+ return;
+ }
+
+ LogUtil.i(
+ "SystemCallLogDataSource.handleInsertsAndUpdates",
+ "found %d entries to insert/update",
+ cursor.getCount());
+
+ if (cursor.moveToFirst()) {
+ int idColumn = cursor.getColumnIndexOrThrow(Calls._ID);
+ int dateColumn = cursor.getColumnIndexOrThrow(Calls.DATE);
+ int lastModifiedColumn = cursor.getColumnIndexOrThrow(Calls.LAST_MODIFIED);
+ int numberColumn = cursor.getColumnIndexOrThrow(Calls.NUMBER);
+ int typeColumn = cursor.getColumnIndexOrThrow(Calls.TYPE);
+ int countryIsoColumn = cursor.getColumnIndexOrThrow(Calls.COUNTRY_ISO);
+ int cachedNameColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_NAME);
+ int cachedFormattedNumberColumn =
+ cursor.getColumnIndexOrThrow(Calls.CACHED_FORMATTED_NUMBER);
+ int cachedPhotoUriColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_PHOTO_URI);
+ int cachedPhotoIdColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_PHOTO_ID);
+ int cachedLookupUriColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_LOOKUP_URI);
+ int cachedNumberTypeColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_NUMBER_TYPE);
+ int cachedNumberLabelColumn = cursor.getColumnIndexOrThrow(Calls.CACHED_NUMBER_LABEL);
+ int isReadColumn = cursor.getColumnIndexOrThrow(Calls.IS_READ);
+ int newColumn = cursor.getColumnIndexOrThrow(Calls.NEW);
+ int geocodedLocationColumn = cursor.getColumnIndexOrThrow(Calls.GEOCODED_LOCATION);
+ int phoneAccountComponentColumn =
+ cursor.getColumnIndexOrThrow(Calls.PHONE_ACCOUNT_COMPONENT_NAME);
+ int phoneAccountIdColumn = cursor.getColumnIndexOrThrow(Calls.PHONE_ACCOUNT_ID);
+ int featuresColumn = cursor.getColumnIndexOrThrow(Calls.FEATURES);
+
+ // The cursor orders by LAST_MODIFIED DESC, so the first result is the most recent timestamp
+ // processed.
+ lastTimestampProcessed = cursor.getLong(lastModifiedColumn);
+ do {
+ long id = cursor.getLong(idColumn);
+ long date = cursor.getLong(dateColumn);
+ String numberAsStr = cursor.getString(numberColumn);
+ long type = cursor.getInt(typeColumn);
+ String countryIso = cursor.getString(countryIsoColumn);
+ String cachedName = cursor.getString(cachedNameColumn);
+ String formattedNumber = cursor.getString(cachedFormattedNumberColumn);
+ String cachedPhotoUri = cursor.getString(cachedPhotoUriColumn);
+ long cachedPhotoId = cursor.getLong(cachedPhotoIdColumn);
+ String cachedLookupUri = cursor.getString(cachedLookupUriColumn);
+ int cachedNumberType = cursor.getInt(cachedNumberTypeColumn);
+ String cachedNumberLabel = cursor.getString(cachedNumberLabelColumn);
+ int isRead = cursor.getInt(isReadColumn);
+ int isNew = cursor.getInt(newColumn);
+ String geocodedLocation = cursor.getString(geocodedLocationColumn);
+ String phoneAccountComponentName = cursor.getString(phoneAccountComponentColumn);
+ String phoneAccountId = cursor.getString(phoneAccountIdColumn);
+ int features = cursor.getInt(featuresColumn);
+
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(AnnotatedCallLog.TIMESTAMP, date);
+
+ if (!TextUtils.isEmpty(numberAsStr)) {
+ byte[] numberAsProtoBytes =
+ dialerPhoneNumberUtil.parse(numberAsStr, countryIso).toByteArray();
+ // TODO(zachh): Need to handle post-dial digits; different on N and M.
+ contentValues.put(AnnotatedCallLog.NUMBER, numberAsProtoBytes);
+ }
- // TODO: Implementation.
+ contentValues.put(AnnotatedCallLog.TYPE, type);
+ contentValues.put(AnnotatedCallLog.NAME, cachedName);
+ contentValues.put(AnnotatedCallLog.FORMATTED_NUMBER, formattedNumber);
+ contentValues.put(AnnotatedCallLog.PHOTO_URI, cachedPhotoUri);
+ contentValues.put(AnnotatedCallLog.PHOTO_ID, cachedPhotoId);
+ contentValues.put(AnnotatedCallLog.LOOKUP_URI, cachedLookupUri);
+
+ // Phone.getTypeLabel returns "Custom" if given (0, null) which is not of any use. Just
+ // omit setting the label if there's no information for it.
+ if (cachedNumberType != 0 || cachedNumberLabel != null) {
+ contentValues.put(
+ AnnotatedCallLog.NUMBER_TYPE_LABEL,
+ Phone.getTypeLabel(appContext.getResources(), cachedNumberType, cachedNumberLabel)
+ .toString());
+ }
+ contentValues.put(AnnotatedCallLog.IS_READ, isRead);
+ contentValues.put(AnnotatedCallLog.NEW, isNew);
+ contentValues.put(AnnotatedCallLog.GEOCODED_LOCATION, geocodedLocation);
+ populatePhoneAccountLabelAndColor(
+ appContext, contentValues, phoneAccountComponentName, phoneAccountId);
+ contentValues.put(AnnotatedCallLog.FEATURES, features);
+
+ if (existingAnnotatedCallLogIds.contains(id)) {
+ mutations.update(id, contentValues);
+ } else {
+ mutations.insert(id, contentValues);
+ }
+ } while (cursor.moveToNext());
+ } // else no new results, do nothing.
+ }
+ }
+
+ private void populatePhoneAccountLabelAndColor(
+ Context appContext,
+ ContentValues contentValues,
+ String phoneAccountComponentName,
+ String phoneAccountId) {
+ PhoneAccountHandle phoneAccountHandle =
+ PhoneAccountUtils.getAccount(phoneAccountComponentName, phoneAccountId);
+ if (phoneAccountHandle == null) {
+ return;
+ }
+ String label = PhoneAccountUtils.getAccountLabel(appContext, phoneAccountHandle);
+ if (TextUtils.isEmpty(label)) {
+ return;
+ }
+ contentValues.put(AnnotatedCallLog.PHONE_ACCOUNT_LABEL, label);
+
+ @ColorInt int color = PhoneAccountUtils.getAccountColor(appContext, phoneAccountHandle);
+ if (color == PhoneAccount.NO_HIGHLIGHT_COLOR) {
+ color =
+ appContext
+ .getResources()
+ .getColor(R.color.dialer_secondary_text_color, appContext.getTheme());
+ }
+ contentValues.put(AnnotatedCallLog.PHONE_ACCOUNT_COLOR, color);
+ }
+
+ private static void handleDeletes(
+ Context appContext, Set<Long> existingAnnotatedCallLogIds, CallLogMutations mutations) {
+ Set<Long> systemCallLogIds =
+ getIdsFromSystemCallLogThatMatch(appContext, existingAnnotatedCallLogIds);
+ LogUtil.i(
+ "SystemCallLogDataSource.handleDeletes",
+ "found %d matching entries in system call log",
+ systemCallLogIds.size());
+ Set<Long> idsInAnnotatedCallLogNoLongerInSystemCallLog = new ArraySet<>();
+ idsInAnnotatedCallLogNoLongerInSystemCallLog.addAll(existingAnnotatedCallLogIds);
+ idsInAnnotatedCallLogNoLongerInSystemCallLog.removeAll(systemCallLogIds);
+
+ LogUtil.i(
+ "SystemCallLogDataSource.handleDeletes",
+ "found %d call log entries to remove",
+ idsInAnnotatedCallLogNoLongerInSystemCallLog.size());
+
+ for (long id : idsInAnnotatedCallLogNoLongerInSystemCallLog) {
+ mutations.delete(id);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources
+ private static Set<Long> getAnnotatedCallLogIds(Context appContext) {
+ ArraySet<Long> ids = new ArraySet<>();
+
+ try (Cursor cursor =
+ appContext
+ .getContentResolver()
+ .query(
+ AnnotatedCallLog.CONTENT_URI,
+ new String[] {AnnotatedCallLog._ID},
+ null,
+ null,
+ null)) {
+
+ if (cursor == null) {
+ LogUtil.e("SystemCallLogDataSource.getAnnotatedCallLogIds", "null cursor");
+ return ids;
+ }
+
+ if (cursor.moveToFirst()) {
+ int idColumn = cursor.getColumnIndexOrThrow(AnnotatedCallLog._ID);
+ do {
+ ids.add(cursor.getLong(idColumn));
+ } while (cursor.moveToNext());
+ }
+ }
+ return ids;
+ }
+
+ @TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources
+ private static Set<Long> getIdsFromSystemCallLogThatMatch(
+ Context appContext, Set<Long> matchingIds) {
+ ArraySet<Long> ids = new ArraySet<>();
+
+ String[] questionMarks = new String[matchingIds.size()];
+ Arrays.fill(questionMarks, "?");
+ String whereClause = (Calls._ID + " in (") + TextUtils.join(",", questionMarks) + ")";
+ String[] whereArgs = new String[matchingIds.size()];
+ int i = 0;
+ for (long id : matchingIds) {
+ whereArgs[i++] = String.valueOf(id);
+ }
+
+ try (Cursor cursor =
+ appContext
+ .getContentResolver()
+ .query(Calls.CONTENT_URI, new String[] {Calls._ID}, whereClause, whereArgs, null)) {
+
+ if (cursor == null) {
+ LogUtil.e("SystemCallLogDataSource.getIdsFromSystemCallLog", "null cursor");
+ return ids;
+ }
+
+ if (cursor.moveToFirst()) {
+ int idColumn = cursor.getColumnIndexOrThrow(Calls._ID);
+ do {
+ ids.add(cursor.getLong(idColumn));
+ } while (cursor.moveToNext());
+ }
+ return ids;
+ }
}
private static class CallLogObserver extends ContentObserver {
diff --git a/java/com/android/dialer/calllog/datasources/util/RowCombiner.java b/java/com/android/dialer/calllog/datasources/util/RowCombiner.java
new file mode 100644
index 000000000..adb7a0742
--- /dev/null
+++ b/java/com/android/dialer/calllog/datasources/util/RowCombiner.java
@@ -0,0 +1,73 @@
+/*
+ * 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.datasources.util;
+
+import android.content.ContentValues;
+import com.android.dialer.common.Assert;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+/** Convenience class for aggregating row values. */
+public class RowCombiner {
+ private final List<ContentValues> individualRowsSortedByTimestampDesc;
+ private final ContentValues combinedRow = new ContentValues();
+
+ public RowCombiner(List<ContentValues> individualRowsSortedByTimestampDesc) {
+ Assert.checkArgument(!individualRowsSortedByTimestampDesc.isEmpty());
+ this.individualRowsSortedByTimestampDesc = individualRowsSortedByTimestampDesc;
+ }
+
+ /** Use the most recent value for the specified column. */
+ public RowCombiner useMostRecentLong(String columnName) {
+ combinedRow.put(columnName, individualRowsSortedByTimestampDesc.get(0).getAsLong(columnName));
+ return this;
+ }
+
+ /** Use the most recent value for the specified column. */
+ public RowCombiner useMostRecentString(String columnName) {
+ combinedRow.put(columnName, individualRowsSortedByTimestampDesc.get(0).getAsString(columnName));
+ return this;
+ }
+
+ /** Asserts that all column values for the given column name are the same, and uses it. */
+ public RowCombiner useSingleValueString(String columnName) {
+ Iterator<ContentValues> iterator = individualRowsSortedByTimestampDesc.iterator();
+ String singleValue = iterator.next().getAsString(columnName);
+ while (iterator.hasNext()) {
+ String current = iterator.next().getAsString(columnName);
+ Assert.checkState(Objects.equals(singleValue, current), "Values different for " + columnName);
+ }
+ combinedRow.put(columnName, singleValue);
+ return this;
+ }
+
+ /** Asserts that all column values for the given column name are the same, and uses it. */
+ public RowCombiner useSingleValueLong(String columnName) {
+ Iterator<ContentValues> iterator = individualRowsSortedByTimestampDesc.iterator();
+ Long singleValue = iterator.next().getAsLong(columnName);
+ while (iterator.hasNext()) {
+ Long current = iterator.next().getAsLong(columnName);
+ Assert.checkState(Objects.equals(singleValue, current), "Values different for " + columnName);
+ }
+ combinedRow.put(columnName, singleValue);
+ return this;
+ }
+
+ public ContentValues combine() {
+ return combinedRow;
+ }
+}
diff --git a/java/com/android/dialer/calllog/ui/AndroidManifest.xml b/java/com/android/dialer/calllog/ui/AndroidManifest.xml
index 228167749..eaf71aba8 100644
--- a/java/com/android/dialer/calllog/ui/AndroidManifest.xml
+++ b/java/com/android/dialer/calllog/ui/AndroidManifest.xml
@@ -13,4 +13,4 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<manifest package="com.android.dialer.calllog"/>
+<manifest package="com.android.dialer.calllog.ui"/>
diff --git a/java/com/android/dialer/calllog/ui/AnnotatedCallLogCursorLoader.java b/java/com/android/dialer/calllog/ui/AnnotatedCallLogCursorLoader.java
deleted file mode 100644
index cd8622e80..000000000
--- a/java/com/android/dialer/calllog/ui/AnnotatedCallLogCursorLoader.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.annotation.TargetApi;
-import android.content.Context;
-import android.content.CursorLoader;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.os.Build;
-import com.android.dialer.calllog.database.AnnotatedCallLog;
-import com.android.dialer.calllog.database.AnnotatedCallLog.Columns;
-
-/** CursorLoader which reads the annotated call log. */
-class AnnotatedCallLogCursorLoader extends CursorLoader {
-
- AnnotatedCallLogCursorLoader(Context context) {
- super(context);
- }
-
- @TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources
- @Override
- public Cursor loadInBackground() {
- try (SQLiteDatabase readableDatabase = AnnotatedCallLog.getReadableDatabase(getContext())) {
- return readableDatabase.rawQuery(
- "SELECT * FROM "
- + AnnotatedCallLog.TABLE_NAME
- + " ORDER BY "
- + Columns.TIMESTAMP
- + " DESC",
- null /* selectionArgs */);
- }
- }
-}
diff --git a/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java
new file mode 100644
index 000000000..d89338350
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java
@@ -0,0 +1,151 @@
+/*
+ * 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.annotation.ColorInt;
+import android.support.annotation.NonNull;
+import android.support.v4.content.CursorLoader;
+import com.android.dialer.CallTypes;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
+import com.android.dialer.common.Assert;
+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 NAME = 2;
+ private static final int FORMATTED_NUMBER = 3;
+ private static final int PHOTO_URI = 4;
+ private static final int PHOTO_ID = 5;
+ private static final int LOOKUP_URI = 6;
+ private static final int NUMBER_TYPE_LABEL = 7;
+ private static final int IS_READ = 8;
+ private static final int NEW = 9;
+ private static final int GEOCODED_LOCATION = 10;
+ private static final int PHONE_ACCOUNT_LABEL = 11;
+ private static final int PHONE_ACCOUNT_COLOR = 12;
+ private static final int FEATURES = 13;
+ private static final int IS_BUSINESS = 14;
+ private static final int IS_VOICEMAIL = 15;
+ private static final int NUMBER_CALLS = 16;
+ private static final int CALL_TYPES = 17;
+
+ /** Convenience class for accessing values using an abbreviated syntax. */
+ static final class Row {
+ private final Cursor cursor;
+
+ Row(Cursor cursor) {
+ this.cursor = cursor;
+ }
+
+ long id() {
+ return cursor.getInt(ID);
+ }
+
+ long timestamp() {
+ return cursor.getLong(TIMESTAMP);
+ }
+
+ String name() {
+ return cursor.getString(NAME);
+ }
+
+ String formattedNumber() {
+ return cursor.getString(FORMATTED_NUMBER);
+ }
+
+ String photoUri() {
+ return cursor.getString(PHOTO_URI);
+ }
+
+ long photoId() {
+ return cursor.getLong(PHOTO_ID);
+ }
+
+ String lookupUri() {
+ return cursor.getString(LOOKUP_URI);
+ }
+
+ String numberTypeLabel() {
+ return cursor.getString(NUMBER_TYPE_LABEL);
+ }
+
+ boolean isRead() {
+ return cursor.getInt(IS_READ) == 1;
+ }
+
+ boolean isNew() {
+ return cursor.getInt(NEW) == 1;
+ }
+
+ String geocodedLocation() {
+ return cursor.getString(GEOCODED_LOCATION);
+ }
+
+ String phoneAccountLabel() {
+ return cursor.getString(PHONE_ACCOUNT_LABEL);
+ }
+
+ @ColorInt
+ int phoneAccountColor() {
+ return cursor.getInt(PHONE_ACCOUNT_COLOR);
+ }
+
+ int features() {
+ return cursor.getInt(FEATURES);
+ }
+
+ boolean isBusiness() {
+ return cursor.getInt(IS_BUSINESS) == 1;
+ }
+
+ boolean isVoicemail() {
+ return cursor.getInt(IS_VOICEMAIL) == 1;
+ }
+
+ int numberCalls() {
+ return cursor.getInt(NUMBER_CALLS);
+ }
+
+ @NonNull
+ CallTypes callTypes() {
+ try {
+ return CallTypes.parseFrom(cursor.getBlob(CALL_TYPES));
+ } catch (InvalidProtocolBufferException e) {
+ throw Assert.createAssertionFailException("Couldn't parse call types", e);
+ }
+ }
+ }
+
+ 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);
+ }
+}
diff --git a/java/com/android/dialer/calllog/ui/HeaderViewHolder.java b/java/com/android/dialer/calllog/ui/HeaderViewHolder.java
new file mode 100644
index 000000000..e4fe029fa
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/HeaderViewHolder.java
@@ -0,0 +1,36 @@
+/*
+ * 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.support.annotation.StringRes;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.View;
+import android.widget.TextView;
+
+/** ViewHolder for {@link NewCallLogAdapter} to display "Today" or "Older" divider row. */
+final class HeaderViewHolder extends ViewHolder {
+
+ private TextView headerTextView;
+
+ HeaderViewHolder(View view) {
+ super(view);
+ headerTextView = view.findViewById(R.id.new_call_log_header_text);
+ }
+
+ void setHeader(@StringRes int header) {
+ headerTextView.setText(header);
+ }
+}
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java b/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java
new file mode 100644
index 000000000..b922a6e3b
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java
@@ -0,0 +1,155 @@
+/*
+ * 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.database.Cursor;
+import android.support.annotation.IntDef;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import com.android.dialer.calllogutils.CallLogDates;
+import com.android.dialer.common.Assert;
+import com.android.dialer.time.Clock;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** {@link RecyclerView.Adapter} for the new call log fragment. */
+final class NewCallLogAdapter extends RecyclerView.Adapter<ViewHolder> {
+
+ /** IntDef for the different types of rows that can be shown in the call log. */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({RowType.HEADER_TODAY, RowType.HEADER_OLDER, RowType.CALL_LOG_ENTRY})
+ @interface RowType {
+ /** Header that displays "Today". */
+ int HEADER_TODAY = 1;
+ /** Header that displays "Older". */
+ int HEADER_OLDER = 2;
+ /** A row representing a call log entry (which could represent one or more calls). */
+ int CALL_LOG_ENTRY = 3;
+ }
+
+ private final Cursor cursor;
+ private final Clock clock;
+
+ /** Null when the "Today" header should not be displayed. */
+ @Nullable private final Integer todayHeaderPosition;
+ /** Null when the "Older" header should not be displayed. */
+ @Nullable private final Integer olderHeaderPosition;
+
+ NewCallLogAdapter(Cursor cursor, Clock clock) {
+ this.cursor = cursor;
+ this.clock = clock;
+
+ // Calculate header adapter positions by reading cursor.
+ long currentTimeMillis = clock.currentTimeMillis();
+ if (cursor.moveToNext()) {
+ CoalescedAnnotatedCallLogCursorLoader.Row firstRow =
+ new CoalescedAnnotatedCallLogCursorLoader.Row(cursor);
+ if (CallLogDates.isSameDay(currentTimeMillis, firstRow.timestamp())) {
+ this.todayHeaderPosition = 0;
+ int adapterPosition = 2; // Accounted for "Today" header and first row.
+ while (cursor.moveToNext()) {
+ CoalescedAnnotatedCallLogCursorLoader.Row row =
+ new CoalescedAnnotatedCallLogCursorLoader.Row(cursor);
+ if (CallLogDates.isSameDay(currentTimeMillis, row.timestamp())) {
+ adapterPosition++;
+ } else {
+ this.olderHeaderPosition = adapterPosition;
+ return;
+ }
+ }
+ this.olderHeaderPosition = null; // Didn't find any "Older" rows.
+ } else {
+ this.todayHeaderPosition = null; // Didn't find any "Today" rows.
+ this.olderHeaderPosition = 0;
+ }
+ } else { // There are no rows, just need to set these because they are final.
+ this.todayHeaderPosition = null;
+ this.olderHeaderPosition = null;
+ }
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup viewGroup, @RowType int viewType) {
+ switch (viewType) {
+ case RowType.HEADER_TODAY:
+ case RowType.HEADER_OLDER:
+ return new HeaderViewHolder(
+ LayoutInflater.from(viewGroup.getContext())
+ .inflate(R.layout.new_call_log_header, viewGroup, false));
+ case RowType.CALL_LOG_ENTRY:
+ return new NewCallLogViewHolder(
+ LayoutInflater.from(viewGroup.getContext())
+ .inflate(R.layout.new_call_log_entry, viewGroup, false),
+ clock);
+ default:
+ throw Assert.createUnsupportedOperationFailException("Unsupported view type: " + viewType);
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder viewHolder, int position) {
+ if (viewHolder instanceof HeaderViewHolder) {
+ HeaderViewHolder headerViewHolder = (HeaderViewHolder) viewHolder;
+ @RowType int viewType = getItemViewType(position);
+ if (viewType == RowType.HEADER_OLDER) {
+ headerViewHolder.setHeader(R.string.new_call_log_header_older);
+ } else if (viewType == RowType.HEADER_TODAY) {
+ headerViewHolder.setHeader(R.string.new_call_log_header_today);
+ } else {
+ throw Assert.createIllegalStateFailException(
+ "Unexpected view type " + viewType + " at position: " + position);
+ }
+ return;
+ }
+ NewCallLogViewHolder newCallLogViewHolder = (NewCallLogViewHolder) viewHolder;
+ int previousHeaders = 0;
+ if (todayHeaderPosition != null && position > todayHeaderPosition) {
+ previousHeaders++;
+ }
+ if (olderHeaderPosition != null && position > olderHeaderPosition) {
+ previousHeaders++;
+ }
+ cursor.moveToPosition(position - previousHeaders);
+ newCallLogViewHolder.bind(cursor);
+ }
+
+ @Override
+ @RowType
+ public int getItemViewType(int position) {
+ if (todayHeaderPosition != null && position == todayHeaderPosition) {
+ return RowType.HEADER_TODAY;
+ }
+ if (olderHeaderPosition != null && position == olderHeaderPosition) {
+ return RowType.HEADER_OLDER;
+ }
+ return RowType.CALL_LOG_ENTRY;
+ }
+
+ @Override
+ public int getItemCount() {
+ int numberOfHeaders = 0;
+ if (todayHeaderPosition != null) {
+ numberOfHeaders++;
+ }
+ if (olderHeaderPosition != null) {
+ numberOfHeaders++;
+ }
+ return cursor.getCount() + numberOfHeaders;
+ }
+}
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
index b8f2b1326..ab7381347 100644
--- a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
+++ b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
@@ -15,32 +15,38 @@
*/
package com.android.dialer.calllog.ui;
-import android.app.Fragment;
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.Context;
-import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager.LoaderCallbacks;
+import android.support.v4.content.Loader;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.CursorAdapter;
-import android.widget.ListView;
-import android.widget.SimpleCursorAdapter;
-import android.widget.TextView;
import com.android.dialer.calllog.CallLogComponent;
import com.android.dialer.calllog.CallLogFramework;
import com.android.dialer.calllog.CallLogFramework.CallLogUi;
-import com.android.dialer.calllog.database.AnnotatedCallLog.Columns;
import com.android.dialer.common.LogUtil;
-import java.text.SimpleDateFormat;
-import java.util.Locale;
+import com.android.dialer.common.concurrent.DialerExecutor;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.concurrent.DialerExecutorFactory;
/** The "new" call log fragment implementation, which is built on top of the annotated call log. */
public final class NewCallLogFragment extends Fragment
implements CallLogUi, LoaderCallbacks<Cursor> {
- private CursorAdapter cursorAdapter;
+ /*
+ * This is a reasonable time that it might take between related call log writes, that also
+ * shouldn't slow down single-writes too much. For example, when populating the database using
+ * the simulator, using this value results in ~6 refresh cycles (on a release build) to write 120
+ * call log entries.
+ */
+ private static final long WAIT_MILLIS = 100L;
+
+ private DialerExecutor<Boolean> refreshAnnotatedCallLogTask;
+ private RecyclerView recyclerView;
public NewCallLogFragment() {
LogUtil.enterBlock("NewCallLogFragment.NewCallLogFragment");
@@ -52,8 +58,28 @@ public final class NewCallLogFragment extends Fragment
LogUtil.enterBlock("NewCallLogFragment.onCreate");
- CallLogFramework callLogFramework = CallLogComponent.get(getContext()).callLogFramework();
+ CallLogComponent component = CallLogComponent.get(getContext());
+ CallLogFramework callLogFramework = component.callLogFramework();
callLogFramework.attachUi(this);
+
+ DialerExecutorFactory dialerExecutorFactory =
+ DialerExecutorComponent.get(getContext()).dialerExecutorFactory();
+
+ // TODO(zachh): Use support fragment manager and add support for them in executors library.
+ refreshAnnotatedCallLogTask =
+ dialerExecutorFactory
+ .createUiTaskBuilder(
+ getActivity().getFragmentManager(),
+ "NewCallLogFragment.refreshAnnotatedCallLog",
+ component.getRefreshAnnotatedCallLogWorker())
+ .build();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ LogUtil.enterBlock("NewCallLogFragment.onStart");
}
@Override
@@ -64,6 +90,9 @@ public final class NewCallLogFragment extends Fragment
CallLogFramework callLogFramework = CallLogComponent.get(getContext()).callLogFramework();
callLogFramework.attachUi(this);
+
+ // TODO(zachh): Consider doing this when fragment becomes visible.
+ checkAnnotatedCallLogDirtyAndRefreshIfNecessary();
}
@Override
@@ -82,57 +111,48 @@ public final class NewCallLogFragment extends Fragment
LogUtil.enterBlock("NewCallLogFragment.onCreateView");
View view = inflater.inflate(R.layout.new_call_log_fragment, container, false);
- ListView listView = (ListView) view.findViewById(R.id.list);
+ recyclerView = view.findViewById(R.id.new_call_log_recycler_view);
- this.cursorAdapter =
- new MyCursorAdapter(
- getContext(),
- R.layout.new_call_log_entry,
- null /* cursor */,
- new String[] {Columns.TIMESTAMP, Columns.CONTACT_NAME},
- new int[] {R.id.timestamp, R.id.contact_name},
- 0);
- listView.setAdapter(cursorAdapter);
-
- getLoaderManager().initLoader(0, null, this);
+ getLoaderManager().restartLoader(0, null, this);
return view;
}
+ private void checkAnnotatedCallLogDirtyAndRefreshIfNecessary() {
+ LogUtil.enterBlock("NewCallLogFragment.checkAnnotatedCallLogDirtyAndRefreshIfNecessary");
+ refreshAnnotatedCallLogTask.executeSerialWithWait(false /* skipDirtyCheck */, WAIT_MILLIS);
+ }
+
@Override
public void invalidateUi() {
LogUtil.enterBlock("NewCallLogFragment.invalidateUi");
- // TODO: Implementation.
+ refreshAnnotatedCallLogTask.executeSerialWithWait(true /* skipDirtyCheck */, WAIT_MILLIS);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- // TODO: This is sort of weird, do we need to implement a content provider?
- return new AnnotatedCallLogCursorLoader(getContext());
+ LogUtil.enterBlock("NewCallLogFragment.onCreateLoader");
+ return new CoalescedAnnotatedCallLogCursorLoader(getContext());
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor newCursor) {
- cursorAdapter.swapCursor(newCursor);
+ LogUtil.enterBlock("NewCallLogFragment.onLoadFinished");
+
+ if (newCursor == null) {
+ // This might be possible when the annotated call log hasn't been created but we're trying
+ // to show the call log.
+ LogUtil.w("NewCallLogFragment.onLoadFinished", "null cursor");
+ return;
+ }
+ // TODO(zachh): Handle empty cursor by showing empty view.
+ recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+ recyclerView.setAdapter(new NewCallLogAdapter(newCursor, System::currentTimeMillis));
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
- cursorAdapter.swapCursor(null);
- }
-
- private static class MyCursorAdapter extends SimpleCursorAdapter {
-
- MyCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
- super(context, layout, c, from, to, flags);
- }
-
- @Override
- public void setViewText(TextView view, String text) {
- if (view.getId() == R.id.timestamp) {
- text = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US).format(Long.valueOf(text));
- }
- view.setText(text);
- }
+ LogUtil.enterBlock("NewCallLogFragment.onLoaderReset");
+ recyclerView.setAdapter(null);
}
}
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
new file mode 100644
index 000000000..e198a38e8
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
@@ -0,0 +1,175 @@
+/*
+ * 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.net.Uri;
+import android.provider.CallLog.Calls;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.QuickContactBadge;
+import android.widget.TextView;
+import com.android.dialer.calllog.ui.CoalescedAnnotatedCallLogCursorLoader.Row;
+import com.android.dialer.calllogutils.CallLogDates;
+import com.android.dialer.calllogutils.CallTypeIconsView;
+import com.android.dialer.contactphoto.ContactPhotoManager;
+import com.android.dialer.lettertile.LetterTileDrawable;
+import com.android.dialer.oem.MotorolaUtils;
+import com.android.dialer.time.Clock;
+import java.util.Locale;
+
+/** {@link RecyclerView.ViewHolder} for the new call log. */
+final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
+
+ private final Context context;
+ private final TextView primaryTextView;
+ private final TextView secondaryTextView;
+ private final QuickContactBadge quickContactBadge;
+ private final CallTypeIconsView primaryCallTypeIconsView; // Used for Wifi, HD icons
+ private final CallTypeIconsView secondaryCallTypeIconsView; // Used for call types
+ private final TextView phoneAccountView;
+ private final Clock clock;
+
+ NewCallLogViewHolder(View view, Clock clock) {
+ super(view);
+ this.context = view.getContext();
+ primaryTextView = view.findViewById(R.id.primary_text);
+ secondaryTextView = view.findViewById(R.id.secondary_text);
+ quickContactBadge = view.findViewById(R.id.quick_contact_photo);
+ primaryCallTypeIconsView = view.findViewById(R.id.primary_call_type_icons);
+ secondaryCallTypeIconsView = view.findViewById(R.id.secondary_call_type_icons);
+ phoneAccountView = view.findViewById(R.id.phone_account);
+ this.clock = clock;
+ }
+
+ /** @param cursor a cursor from {@link CoalescedAnnotatedCallLogCursorLoader}. */
+ void bind(Cursor cursor) {
+ CoalescedAnnotatedCallLogCursorLoader.Row row =
+ new CoalescedAnnotatedCallLogCursorLoader.Row(cursor);
+
+ // TODO(zachh): Handle RTL properly.
+ primaryTextView.setText(buildPrimaryText(row));
+ secondaryTextView.setText(buildSecondaryText(row));
+
+ if (row.isNew()) {
+ // TODO(zachh): Figure out correct styling for new/missed/unread calls.
+ primaryTextView.setTextAppearance(R.style.primary_textview_new_call);
+ // TODO(zachh): Styling for call type icons when the call is new.
+ secondaryTextView.setTextAppearance(R.style.secondary_textview_new_call);
+ }
+
+ setPhoto(row);
+ setPrimaryCallTypes(row);
+ setSecondaryCallTypes(row);
+ setPhoneAccounts(row);
+ }
+
+ private String buildPrimaryText(CoalescedAnnotatedCallLogCursorLoader.Row row) {
+ StringBuilder primaryText = new StringBuilder();
+ if (!TextUtils.isEmpty(row.name())) {
+ primaryText.append(row.name());
+ } else if (!TextUtils.isEmpty(row.formattedNumber())) {
+ primaryText.append(row.formattedNumber());
+ } else {
+ // TODO(zachh): Handle CallLog.Calls.PRESENTATION_*, including Verizon restricted numbers.
+ primaryText.append(context.getText(R.string.new_call_log_unknown));
+ }
+ if (row.numberCalls() > 1) {
+ primaryText.append(String.format(Locale.getDefault(), " (%d)", row.numberCalls()));
+ }
+ return primaryText.toString();
+ }
+
+ private String buildSecondaryText(CoalescedAnnotatedCallLogCursorLoader.Row row) {
+ /*
+ * Rules: (Duo video, )?$Label|$Location • Date
+ *
+ * Examples:
+ * Duo Video, Mobile • Now
+ * Duo Video • 11:45pm
+ * Mobile • 11:45pm
+ * Mobile • Sunday
+ * Brooklyn, NJ • Jan 15
+ *
+ * Date rules:
+ * if < 1 minute ago: "Now"; else if today: HH:MM(am|pm); else if < 3 days: day; else: MON D
+ */
+ StringBuilder secondaryText = new StringBuilder();
+ if ((row.features() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) {
+ // TODO(zachh): Add "Duo" prefix?
+ secondaryText.append(context.getText(R.string.new_call_log_video));
+ }
+ String numberTypeLabel = row.numberTypeLabel();
+ if (!TextUtils.isEmpty(numberTypeLabel)) {
+ if (secondaryText.length() > 0) {
+ secondaryText.append(", ");
+ }
+ secondaryText.append(numberTypeLabel);
+ } else { // If there's a number type label, don't show the location.
+ String location = row.geocodedLocation();
+ if (!TextUtils.isEmpty(location)) {
+ if (secondaryText.length() > 0) {
+ secondaryText.append(", ");
+ }
+ secondaryText.append(location);
+ }
+ }
+ if (secondaryText.length() > 0) {
+ secondaryText.append(" • ");
+ }
+ secondaryText.append(
+ CallLogDates.newCallLogTimestampLabel(context, clock.currentTimeMillis(), row.timestamp()));
+ return secondaryText.toString();
+ }
+
+ private void setPhoto(Row row) {
+ // TODO(zachh): Set the contact type.
+ ContactPhotoManager.getInstance(context)
+ .loadDialerThumbnailOrPhoto(
+ quickContactBadge,
+ row.lookupUri() == null ? null : Uri.parse(row.lookupUri()),
+ row.photoId(),
+ row.photoUri() == null ? null : Uri.parse(row.photoUri()),
+ row.name(),
+ LetterTileDrawable.TYPE_DEFAULT);
+ }
+
+ private void setPrimaryCallTypes(Row row) {
+ // Only HD and Wifi icons are shown following the primary text.
+ primaryCallTypeIconsView.setShowHd(
+ MotorolaUtils.shouldShowHdIconInCallLog(context, row.features()));
+ primaryCallTypeIconsView.setShowWifi(
+ MotorolaUtils.shouldShowWifiIconInCallLog(context, row.features()));
+ }
+
+ private void setSecondaryCallTypes(Row row) {
+ // Only call type icons are shown before the secondary text.
+ for (int callType : row.callTypes().getTypeList()) {
+ secondaryCallTypeIconsView.add(callType);
+ }
+ // TODO(zachh): Per new mocks, may need to add method to CallTypeIconsView to disable coloring.
+ }
+
+ private void setPhoneAccounts(Row row) {
+ if (row.phoneAccountLabel() != null) {
+ phoneAccountView.setText(row.phoneAccountLabel());
+ phoneAccountView.setTextColor(row.phoneAccountColor());
+ phoneAccountView.setVisibility(View.VISIBLE);
+ }
+ }
+}
diff --git a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_entry.xml b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_entry.xml
index ee3efd002..77ba68124 100644
--- a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_entry.xml
+++ b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_entry.xml
@@ -15,19 +15,97 @@
~ limitations under the License
-->
-<LinearLayout
+<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/call_log_entry_top_margin"
+ android:paddingTop="@dimen/call_log_entry_padding_top_start"
+ android:paddingBottom="@dimen/call_log_entry_padding_bottom_end"
+ android:paddingStart="@dimen/call_log_entry_padding_top_start"
+ android:paddingEnd="@dimen/call_log_entry_padding_bottom_end"
+ android:gravity="center_vertical">
- <TextView
- android:id="@+id/timestamp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ <QuickContactBadge
+ android:id="@+id/quick_contact_photo"
+ android:layout_width="@dimen/call_log_entry_photo_size"
+ android:layout_height="@dimen/call_log_entry_photo_size"
+ android:layout_centerVertical="true"
+ android:padding="@dimen/call_log_entry_photo_padding"
+ android:focusable="true"/>
- <TextView
- android:id="@+id/contact_name"
+ <LinearLayout
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-</LinearLayout> \ No newline at end of file
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@+id/quick_contact_photo"
+ android:layout_toStartOf="@+id/menu_button"
+ android:orientation="vertical">
+
+ <!-- TODO(zachh): Optimize this layout -->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/primary_text"
+ style="@style/PrimaryText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/call_log_entry_photo_text_margin"/>
+
+ <!-- HD and Wifi icons are shown adjacent to primary text. Call types are shown adjacent to
+ secondary text (below). -->
+ <com.android.dialer.calllogutils.CallTypeIconsView
+ android:id="@+id/primary_call_type_icons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_gravity="center_vertical"/>
+
+ </LinearLayout>
+
+ <!-- TODO(zachh): Optimize this layout -->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <!-- Only call types are shown adjacent to secondary text. HD and Wifi icons are shown
+ adjacent to primary text (above). -->
+ <com.android.dialer.calllogutils.CallTypeIconsView
+ android:id="@+id/secondary_call_type_icons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_gravity="center_vertical"/>
+
+ <TextView
+ android:id="@+id/secondary_text"
+ style="@style/SecondaryText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/call_log_entry_photo_text_margin"/>
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/phone_account"
+ style="@style/SecondaryText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/call_log_entry_photo_text_margin"
+ android:visibility="gone"/>
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/menu_button"
+ android:layout_width="@dimen/call_log_entry_menu_button_size"
+ android:layout_height="@dimen/call_log_entry_menu_button_size"
+ android:layout_alignParentEnd="true"
+ android:layout_centerVertical="true"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:scaleType="center"
+ android:src="@drawable/quantum_ic_more_vert_vd_theme_24"
+ android:tint="@color/dialer_secondary_text_color"/>
+</RelativeLayout>
diff --git a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml
index 433dbdd0f..e1d8410b6 100644
--- a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml
+++ b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml
@@ -15,8 +15,9 @@
~ limitations under the License
-->
-<ListView
+<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list"
+ android:id="@+id/new_call_log_recycler_view"
android:layout_width="match_parent"
- android:layout_height="match_parent"/>
+ android:layout_height="match_parent"
+ android:background="@color/background_dialer_light"/>
diff --git a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_header.xml b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_header.xml
new file mode 100644
index 000000000..13575db55
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_header.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:height="48dp">
+ <TextView
+ android:id="@+id/new_call_log_header_text"
+ style="@style/SecondaryText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/call_log_action_icon_margin_start"
+ android:layout_centerVertical="true"/>
+</RelativeLayout>
diff --git a/java/com/android/dialer/calllog/ui/res/values-af/strings.xml b/java/com/android/dialer/calllog/ui/res/values-af/strings.xml
new file mode 100644
index 000000000..c6b69b508
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-af/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Onbekend"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Vandag"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Ouer"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-am/strings.xml b/java/com/android/dialer/calllog/ui/res/values-am/strings.xml
new file mode 100644
index 000000000..adde37b37
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-am/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ቪዲዮ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"ያልታወቀ"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"ዛሬ"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"የቆዩ"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ar/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ar/strings.xml
new file mode 100644
index 000000000..492ee4280
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ar/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"فيديو"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"غير معروف"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"اليوم"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"أقدم"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-az/strings.xml b/java/com/android/dialer/calllog/ui/res/values-az/strings.xml
new file mode 100644
index 000000000..1e7e57bf3
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-az/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Naməlum"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Bu gün"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Keçmiş"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-b+sr+Latn/strings.xml b/java/com/android/dialer/calllog/ui/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 000000000..e60fa61bc
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video poziv"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Nepoznat broj"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Danas"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Ranije"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-be/strings.xml b/java/com/android/dialer/calllog/ui/res/values-be/strings.xml
new file mode 100644
index 000000000..c4e80c162
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-be/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Відэа"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Невядома"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Сёння"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Больш старыя"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-bg/strings.xml b/java/com/android/dialer/calllog/ui/res/values-bg/strings.xml
new file mode 100644
index 000000000..8806cc161
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-bg/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Видеообаждане"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Неизвестен"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Днес"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"По-стари"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-bn/strings.xml b/java/com/android/dialer/calllog/ui/res/values-bn/strings.xml
new file mode 100644
index 000000000..5c374d11a
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-bn/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ভিডিও"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"অজানা"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"আজ"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"পুরনো"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-bs/strings.xml b/java/com/android/dialer/calllog/ui/res/values-bs/strings.xml
new file mode 100644
index 000000000..3d1b302ca
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-bs/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Videozapis"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Nepoznato"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Danas"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Starije"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ca/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ca/strings.xml
new file mode 100644
index 000000000..54d07f594
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ca/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Vídeo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Desconeguts"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Avui"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Anteriors"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-cs/strings.xml b/java/com/android/dialer/calllog/ui/res/values-cs/strings.xml
new file mode 100644
index 000000000..40a9cb1f2
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-cs/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Neznámý volající"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Dnes"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Starší"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-da/strings.xml b/java/com/android/dialer/calllog/ui/res/values-da/strings.xml
new file mode 100644
index 000000000..46a87a4c4
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-da/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Ukendt"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"I dag"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Ældre"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-de/strings.xml b/java/com/android/dialer/calllog/ui/res/values-de/strings.xml
new file mode 100644
index 000000000..e587bb3d6
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-de/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Unbekannt"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Heute"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Ältere"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-el/strings.xml b/java/com/android/dialer/calllog/ui/res/values-el/strings.xml
new file mode 100644
index 000000000..9f40423dc
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-el/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Βίντεο"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Άγνωστος"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Σήμερα"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Παλαιότερες"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-en-rAU/strings.xml b/java/com/android/dialer/calllog/ui/res/values-en-rAU/strings.xml
new file mode 100644
index 000000000..b442d5a16
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-en-rAU/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Unknown"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Today"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Older"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-en-rGB/strings.xml b/java/com/android/dialer/calllog/ui/res/values-en-rGB/strings.xml
new file mode 100644
index 000000000..b442d5a16
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-en-rGB/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Unknown"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Today"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Older"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-en-rIN/strings.xml b/java/com/android/dialer/calllog/ui/res/values-en-rIN/strings.xml
new file mode 100644
index 000000000..b442d5a16
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-en-rIN/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Unknown"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Today"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Older"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-es-rUS/strings.xml b/java/com/android/dialer/calllog/ui/res/values-es-rUS/strings.xml
new file mode 100644
index 000000000..5cfdae785
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-es-rUS/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Desconocido"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Hoy"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Anterior"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-es/strings.xml b/java/com/android/dialer/calllog/ui/res/values-es/strings.xml
new file mode 100644
index 000000000..c23e7cf74
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-es/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Vídeo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Desconocidas"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Hoy"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Anteriores"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-et/strings.xml b/java/com/android/dialer/calllog/ui/res/values-et/strings.xml
new file mode 100644
index 000000000..0199758d7
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-et/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Tundmatu"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Täna"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Vanem"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-eu/strings.xml b/java/com/android/dialer/calllog/ui/res/values-eu/strings.xml
new file mode 100644
index 000000000..eea5b7866
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-eu/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Bideoa"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Ezezagunak"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Gaurkoak"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Zaharragoak"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-fa/strings.xml b/java/com/android/dialer/calllog/ui/res/values-fa/strings.xml
new file mode 100644
index 000000000..0b9b19f51
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-fa/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ویدیو"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"نامشخص"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"امروز"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"قدیمی‌تر"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-fi/strings.xml b/java/com/android/dialer/calllog/ui/res/values-fi/strings.xml
new file mode 100644
index 000000000..295488278
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-fi/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Videopuhelu"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Tuntematon"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Tänään"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Vanhemmat"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-fr-rCA/strings.xml b/java/com/android/dialer/calllog/ui/res/values-fr-rCA/strings.xml
new file mode 100644
index 000000000..dd1a34cb1
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-fr-rCA/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Vidéo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Inconnu"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Aujourd\'hui"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Plus anciens"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-fr/strings.xml b/java/com/android/dialer/calllog/ui/res/values-fr/strings.xml
new file mode 100644
index 000000000..ddeaf1925
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-fr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Vidéo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Numéro inconnu"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Aujourd\'hui"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Plus anciens"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-gl/strings.xml b/java/com/android/dialer/calllog/ui/res/values-gl/strings.xml
new file mode 100644
index 000000000..248611923
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-gl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Vídeo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Descoñecidos"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Hoxe"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Anteriores"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-gu/strings.xml b/java/com/android/dialer/calllog/ui/res/values-gu/strings.xml
new file mode 100644
index 000000000..6235641d0
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-gu/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"વીડિઓ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"અજાણ"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"આજે"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"જૂનું"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-hi/strings.xml b/java/com/android/dialer/calllog/ui/res/values-hi/strings.xml
new file mode 100644
index 000000000..3c3ccc8ef
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-hi/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"वीडियो"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"अज्ञात"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"आज"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"पुराना"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-hr/strings.xml b/java/com/android/dialer/calllog/ui/res/values-hr/strings.xml
new file mode 100644
index 000000000..614f46c3a
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-hr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Videopoziv"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Nepoznato"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Danas"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Stariji"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-hu/strings.xml b/java/com/android/dialer/calllog/ui/res/values-hu/strings.xml
new file mode 100644
index 000000000..0dc4e9295
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-hu/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Videó"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Ismeretlen"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Ma"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Korábbi"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-hy/strings.xml b/java/com/android/dialer/calllog/ui/res/values-hy/strings.xml
new file mode 100644
index 000000000..6c13619ef
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-hy/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Տեսանյութ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Անհայտ"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Այսօր"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Ավելի հին"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-in/strings.xml b/java/com/android/dialer/calllog/ui/res/values-in/strings.xml
new file mode 100644
index 000000000..ee18199df
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-in/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Tidak diketahui"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Hari ini"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Lebih lama"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-is/strings.xml b/java/com/android/dialer/calllog/ui/res/values-is/strings.xml
new file mode 100644
index 000000000..80cf17ed8
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-is/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Myndsímtal"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Óþekkt"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Í dag"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Eldra"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-it/strings.xml b/java/com/android/dialer/calllog/ui/res/values-it/strings.xml
new file mode 100644
index 000000000..039081ea6
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-it/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Sconosciuto"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Oggi"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Meno recenti"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-iw/strings.xml b/java/com/android/dialer/calllog/ui/res/values-iw/strings.xml
new file mode 100644
index 000000000..4d906edf6
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-iw/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"וידאו"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"לא ידוע"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"היום"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"ישנות יותר"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ja/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ja/strings.xml
new file mode 100644
index 000000000..660392d2f
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ja/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ビデオ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"不明"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"今日"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"昨日以前"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ka/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ka/strings.xml
new file mode 100644
index 000000000..a6787839c
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ka/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ვიდეო"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"უცნობი"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"დღეს"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"უფრო ძველი"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-kk/strings.xml b/java/com/android/dialer/calllog/ui/res/values-kk/strings.xml
new file mode 100644
index 000000000..830285926
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-kk/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Бейне"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Белгісіз"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Бүгін"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Ескілеу"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-km/strings.xml b/java/com/android/dialer/calllog/ui/res/values-km/strings.xml
new file mode 100644
index 000000000..dfaca9af8
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-km/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"វីដេអូ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"មិន​ស្គាល់"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"ថ្ងៃនេះ"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"ចាស់ៗ"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-kn/strings.xml b/java/com/android/dialer/calllog/ui/res/values-kn/strings.xml
new file mode 100644
index 000000000..5c764a29c
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-kn/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ವೀಡಿಯೊ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"ಅಪರಿಚಿತ"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"ಇಂದು"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"ಹಳೆಯದು"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ko/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ko/strings.xml
new file mode 100644
index 000000000..094c3d93b
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ko/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"동영상"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"알 수 없음"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"오늘"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"이전"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ky/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ky/strings.xml
new file mode 100644
index 000000000..d15a2b2b6
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ky/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Видео"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Белгисиз"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Бүгүн"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Мурункураак"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-lo/strings.xml b/java/com/android/dialer/calllog/ui/res/values-lo/strings.xml
new file mode 100644
index 000000000..b869bbd48
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-lo/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ວິດີໂອ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"ບໍ່ຮູ້ຈັກ"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"ມື້ນີ້"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"ເກົ່າກວ່າ"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-lt/strings.xml b/java/com/android/dialer/calllog/ui/res/values-lt/strings.xml
new file mode 100644
index 000000000..1701fa298
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-lt/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Vaizdo įrašas"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Nežinoma"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Šiandien"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Senesni"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-lv/strings.xml b/java/com/android/dialer/calllog/ui/res/values-lv/strings.xml
new file mode 100644
index 000000000..adce799f7
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-lv/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Videozvans"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Nezināmi"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Šodien"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Vecāki zvani"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-mk/strings.xml b/java/com/android/dialer/calllog/ui/res/values-mk/strings.xml
new file mode 100644
index 000000000..e347f1a07
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-mk/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Видео"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Непознато"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Денес"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Постари"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ml/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ml/strings.xml
new file mode 100644
index 000000000..7d1fcd115
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ml/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"വീഡിയോ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"അജ്ഞാതം"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"ഇന്ന്"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"പഴയത്"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-mn/strings.xml b/java/com/android/dialer/calllog/ui/res/values-mn/strings.xml
new file mode 100644
index 000000000..bdaf835a2
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-mn/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Видео"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Тодорхойгүй"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Өнөөдөр"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Хуучин"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-mr/strings.xml b/java/com/android/dialer/calllog/ui/res/values-mr/strings.xml
new file mode 100644
index 000000000..5c348d16d
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-mr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"व्हिडिओ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"अज्ञात"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"आज"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"अधिक जुने"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ms/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ms/strings.xml
new file mode 100644
index 000000000..ee18199df
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ms/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Tidak diketahui"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Hari ini"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Lebih lama"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-my/strings.xml b/java/com/android/dialer/calllog/ui/res/values-my/strings.xml
new file mode 100644
index 000000000..f841bd51f
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-my/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ဗီဒီယို"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"အမည်မသိ"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"ယနေ့"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"ယခင်နေ့များက"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-nb/strings.xml b/java/com/android/dialer/calllog/ui/res/values-nb/strings.xml
new file mode 100644
index 000000000..9cf3273f2
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-nb/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Ukjent"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"I dag"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Eldre"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ne/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ne/strings.xml
new file mode 100644
index 000000000..dc1c617e4
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ne/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"भिडियो कल"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"अज्ञात कल"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"आज"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"अझ पुरानो"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-nl/strings.xml b/java/com/android/dialer/calllog/ui/res/values-nl/strings.xml
new file mode 100644
index 000000000..96531873c
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-nl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Onbekend"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Vandaag"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Ouder"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-no/strings.xml b/java/com/android/dialer/calllog/ui/res/values-no/strings.xml
new file mode 100644
index 000000000..9cf3273f2
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-no/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Ukjent"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"I dag"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Eldre"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-pa/strings.xml b/java/com/android/dialer/calllog/ui/res/values-pa/strings.xml
new file mode 100644
index 000000000..797b55ed6
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-pa/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ਵੀਡੀਓ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"ਅਗਿਆਤ"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"ਅੱਜ"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"ਵਧੇਰੇ ਪੁਰਾਣਾ"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-pl/strings.xml b/java/com/android/dialer/calllog/ui/res/values-pl/strings.xml
new file mode 100644
index 000000000..3c600288a
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-pl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Rozmowa wideo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Nieznany"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Dzisiaj"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Starsze"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-pt-rBR/strings.xml b/java/com/android/dialer/calllog/ui/res/values-pt-rBR/strings.xml
new file mode 100644
index 000000000..7b65f3a26
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-pt-rBR/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Vídeo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Número desconhecido"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Hoje"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Mais antigas"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-pt-rPT/strings.xml b/java/com/android/dialer/calllog/ui/res/values-pt-rPT/strings.xml
new file mode 100644
index 000000000..f7491b97e
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-pt-rPT/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Vídeo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Desconhecido"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Hoje"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Mais antigas"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-pt/strings.xml b/java/com/android/dialer/calllog/ui/res/values-pt/strings.xml
new file mode 100644
index 000000000..7b65f3a26
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-pt/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Vídeo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Número desconhecido"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Hoje"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Mais antigas"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ro/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ro/strings.xml
new file mode 100644
index 000000000..5446a7109
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ro/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Necunoscut"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Astăzi"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Mai vechi"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ru/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ru/strings.xml
new file mode 100644
index 000000000..b8d85e986
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ru/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Видеовызов"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Неизвестно"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Сегодня"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Раньше"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-si/strings.xml b/java/com/android/dialer/calllog/ui/res/values-si/strings.xml
new file mode 100644
index 000000000..0aad640ea
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-si/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"වීඩියෝ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"නොදන්නා"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"අද"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"වඩා පරණ"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-sk/strings.xml b/java/com/android/dialer/calllog/ui/res/values-sk/strings.xml
new file mode 100644
index 000000000..083fad4f4
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-sk/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Neznáme"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Dnes"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Staršie"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-sl/strings.xml b/java/com/android/dialer/calllog/ui/res/values-sl/strings.xml
new file mode 100644
index 000000000..38b651ed2
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-sl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Neznano"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Danes"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Starejše"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-sq/strings.xml b/java/com/android/dialer/calllog/ui/res/values-sq/strings.xml
new file mode 100644
index 000000000..f5659af4b
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-sq/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"I panjohur"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Sot"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Më të vjetra"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-sr/strings.xml b/java/com/android/dialer/calllog/ui/res/values-sr/strings.xml
new file mode 100644
index 000000000..dfae73305
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-sr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Видео позив"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Непознат број"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Данас"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Раније"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-sv/strings.xml b/java/com/android/dialer/calllog/ui/res/values-sv/strings.xml
new file mode 100644
index 000000000..20c2fda22
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-sv/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Okänd"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"I dag"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Äldre"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-sw/strings.xml b/java/com/android/dialer/calllog/ui/res/values-sw/strings.xml
new file mode 100644
index 000000000..04390619f
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-sw/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Haijulikani"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Leo"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Za zamani"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ta/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ta/strings.xml
new file mode 100644
index 000000000..f883fecc9
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ta/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"வீடியோ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"தெரியாத எண்கள்"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"இன்று"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"பழையவை"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-te/strings.xml b/java/com/android/dialer/calllog/ui/res/values-te/strings.xml
new file mode 100644
index 000000000..6c3bd442c
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-te/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"వీడియో"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"తెలియదు"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"ఈ రోజు"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"పాతది"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-th/strings.xml b/java/com/android/dialer/calllog/ui/res/values-th/strings.xml
new file mode 100644
index 000000000..8afc82acc
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-th/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"วิดีโอ"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"ไม่ทราบ"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"วันนี้"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"เก่ากว่า"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-tl/strings.xml b/java/com/android/dialer/calllog/ui/res/values-tl/strings.xml
new file mode 100644
index 000000000..34d6f2c8e
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-tl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Hindi Alam"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Ngayong araw"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Mas Luma"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-tr/strings.xml b/java/com/android/dialer/calllog/ui/res/values-tr/strings.xml
new file mode 100644
index 000000000..e7ada3ded
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-tr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Görünt. görüşme"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Bilinmiyor"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Bugün"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Eski"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-uk/strings.xml b/java/com/android/dialer/calllog/ui/res/values-uk/strings.xml
new file mode 100644
index 000000000..0de770d0b
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-uk/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Відео"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Невідомо"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Сьогодні"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Старіші"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-ur/strings.xml b/java/com/android/dialer/calllog/ui/res/values-ur/strings.xml
new file mode 100644
index 000000000..16ae08a94
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-ur/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"ویڈیو"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"نامعلوم"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"آج"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"قدیم تر"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-uz/strings.xml b/java/com/android/dialer/calllog/ui/res/values-uz/strings.xml
new file mode 100644
index 000000000..22e4d18c1
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-uz/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video suhbat"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Noma’lum"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Bugun"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Eskiroq"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-vi/strings.xml b/java/com/android/dialer/calllog/ui/res/values-vi/strings.xml
new file mode 100644
index 000000000..a70de21fa
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-vi/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Video"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Không xác định"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Hôm nay"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Cũ hơn"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-zh-rCN/strings.xml b/java/com/android/dialer/calllog/ui/res/values-zh-rCN/strings.xml
new file mode 100644
index 000000000..ae4c6450b
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-zh-rCN/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"视频通话"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"未知"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"今天"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"更早"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-zh-rHK/strings.xml b/java/com/android/dialer/calllog/ui/res/values-zh-rHK/strings.xml
new file mode 100644
index 000000000..4e7829292
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-zh-rHK/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"影片"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"不明"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"今天"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"較舊"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-zh-rTW/strings.xml b/java/com/android/dialer/calllog/ui/res/values-zh-rTW/strings.xml
new file mode 100644
index 000000000..4b6b73680
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-zh-rTW/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"視訊通話"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"不明"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"今天"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"較舊"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values-zu/strings.xml b/java/com/android/dialer/calllog/ui/res/values-zu/strings.xml
new file mode 100644
index 000000000..675e632d9
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values-zu/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="new_call_log_video" msgid="8414984483082880050">"Ividiyo"</string>
+ <string name="new_call_log_unknown" msgid="7873134340045098010">"Akwaziwa"</string>
+ <string name="new_call_log_header_today" msgid="3849627842127894230">"Namhlanje"</string>
+ <string name="new_call_log_header_older" msgid="5879512250610285872">"Okudala"</string>
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values/dimens.xml b/java/com/android/dialer/calllog/ui/res/values/dimens.xml
new file mode 100644
index 000000000..bfb4c99d7
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values/dimens.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<resources>
+
+ <!-- call log entries -->
+ <dimen name="call_log_entry_top_margin">6dp</dimen>
+ <dimen name="call_log_entry_padding_bottom_end">16dp</dimen>
+ <dimen name="call_log_entry_padding_top_start">12dp</dimen>
+ <dimen name="call_log_entry_photo_size">48dp</dimen>
+ <dimen name="call_log_entry_photo_padding">4dp</dimen>
+ <dimen name="call_log_entry_photo_text_margin">8dp</dimen>
+ <dimen name="call_log_entry_menu_button_size">48dp</dimen>
+
+</resources>
diff --git a/java/com/android/dialer/calllog/ui/res/values/strings.xml b/java/com/android/dialer/calllog/ui/res/values/strings.xml
new file mode 100644
index 000000000..9b044ca08
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources>
+
+ <!-- Text to show in call log for a video call. [CHAR LIMIT=16] -->
+ <string name="new_call_log_video">Video</string>
+
+ <!-- String used to display calls from unknown numbers in the call log. [CHAR LIMIT=30] -->
+ <string name="new_call_log_unknown">Unknown</string>
+
+ <!-- Header in call log to group calls from the current day. [CHAR LIMIT=30] -->
+ <string name="new_call_log_header_today">Today</string>
+
+ <!-- Header in call log to group calls from before the current day. [CHAR LIMIT=30] -->
+ <string name="new_call_log_header_older">Older</string>
+
+</resources> \ No newline at end of file
diff --git a/java/com/android/dialer/calllog/ui/res/values/styles.xml b/java/com/android/dialer/calllog/ui/res/values/styles.xml
new file mode 100644
index 000000000..23cb93e1a
--- /dev/null
+++ b/java/com/android/dialer/calllog/ui/res/values/styles.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 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
+ -->
+<resources>
+
+ <style name="primary_textview_new_call">
+ <item name="android:fontFamily">sans-serif-medium</item>
+ </style>
+
+ <style name="secondary_textview_new_call">
+ <item name="android:textColor">@color/missed_call</item>
+ <item name="android:fontFamily">sans-serif-medium</item>
+ </style>
+
+</resources> \ No newline at end of file