Merge "Use Call Redirection service in Telecom"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9abe7e7..6aac49e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -297,18 +297,10 @@
             </intent-filter>
         </activity>
 
-        <activity android:name="com.android.server.telecom.components.ChangeDefaultCallScreeningApp"
-            android:label="@string/change_default_dialer_dialog_title"
-            android:excludeFromRecents="true"
-            android:theme="@*android:style/Theme.Material.Light.Dialog.Alert"
-            android:priority="1000"
-            android:process=":ui">
-        </activity>
-
         <activity android:name=".ui.TelecomDeveloperMenu"
-                android:label="@string/developer_title"
-                android:exported="false"
-                android:process=":ui" />
+                  android:label="@string/developer_title"
+                  android:exported="false"
+                  android:process=":ui" />
 
         <service android:name=".components.BluetoothPhoneService"
                 android:singleUser="true"
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index 61f7a30..1d3a90e 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -31,6 +31,9 @@
 import com.android.server.telecom.nano.TelecomLogClass;
 
 import java.io.PrintWriter;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -39,6 +42,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.PriorityQueue;
+import java.util.concurrent.LinkedBlockingDeque;
 import java.util.stream.Collectors;
 
 import static android.telecom.ParcelableCallAnalytics.AnalyticsEvent;
@@ -578,8 +582,11 @@
     public static final long MILLIS_IN_1_SECOND = ParcelableCallAnalytics.MILLIS_IN_1_SECOND;
 
     public static final int MAX_NUM_CALLS_TO_STORE = 100;
+    public static final int MAX_NUM_DUMP_TIMES_TO_STORE = 100;
 
     private static final Object sLock = new Object(); // Coarse lock for all of analytics
+    private static final LinkedBlockingDeque<Long> sDumpTimes =
+            new LinkedBlockingDeque<>(MAX_NUM_DUMP_TIMES_TO_STORE);
     private static final Map<String, CallInfoImpl> sCallIdToInfo = new HashMap<>();
     private static final LinkedList<String> sActiveCallIds = new LinkedList<>();
     private static final List<SessionTiming> sSessionTimings = new LinkedList<>();
@@ -625,6 +632,7 @@
         TelecomLogClass.TelecomLog result = new TelecomLogClass.TelecomLog();
 
         synchronized (sLock) {
+            noteDumpTime();
             result.callLogs = sCallIdToInfo.values().stream()
                     .map(CallInfoImpl::toProto)
                     .toArray(TelecomLogClass.CallLog[]::new);
@@ -680,6 +688,12 @@
                     .forEach(e -> writer.printf("%s: %.2f\n",
                             sSessionIdToLogSession.get(e.getKey()), e.getValue()));
             writer.println("Hardware Version: " + SystemProperties.get("ro.boot.revision", ""));
+            writer.println("Past analytics dumps: ");
+            writer.increaseIndent();
+            for (long time : sDumpTimes) {
+                writer.println(Instant.ofEpochMilli(time).atZone(ZoneOffset.UTC));
+            }
+            writer.decreaseIndent();
         }
     }
 
@@ -689,6 +703,17 @@
         }
     }
 
+    public static void noteDumpTime() {
+        if (sDumpTimes.remainingCapacity() == 0) {
+            sDumpTimes.removeLast();
+        }
+        try {
+            sDumpTimes.addFirst(System.currentTimeMillis());
+        } catch (IllegalStateException e) {
+            Log.w(TAG, "Failed to note dump time -- full");
+        }
+    }
+
     /**
      * Returns a copy of callIdToInfo. Use only for testing.
      */
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 2a7b25d..dfd7b2c 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -32,6 +32,7 @@
 import android.os.Trace;
 import android.provider.ContactsContract.Contacts;
 import android.telecom.CallAudioState;
+import android.telecom.CallIdentification;
 import android.telecom.Conference;
 import android.telecom.ConnectionService;
 import android.telecom.DisconnectCause;
@@ -141,6 +142,7 @@
                                  Bundle extras, boolean isLegacy);
         void onHandoverFailed(Call call, int error);
         void onHandoverComplete(Call call);
+        void onCallIdentificationChanged(Call call);
     }
 
     public abstract static class ListenerBase implements Listener {
@@ -219,6 +221,8 @@
         public void onHandoverFailed(Call call, int error) {}
         @Override
         public void onHandoverComplete(Call call) {}
+        @Override
+        public void onCallIdentificationChanged(Call call) {}
     }
 
     private final CallerInfoLookupHelper.OnQueryCompleteListener mCallerInfoQueryListener =
@@ -530,6 +534,11 @@
     private boolean mIsUsingCallFiltering = false;
 
     /**
+     * {@link CallIdentification} provided by a {@link android.telecom.CallScreeningService}.
+     */
+    private CallIdentification mCallIdentification = null;
+
+    /**
      * Persists the specified parameters and initializes the new instance.
      * @param context The context.
      * @param repository The connection service repository.
@@ -3126,4 +3135,27 @@
     public void setIsUsingCallFiltering(boolean isUsingCallFiltering) {
         mIsUsingCallFiltering = isUsingCallFiltering;
     }
+
+    /**
+     * Update the {@link CallIdentification} for a call.
+     * @param callIdentification the {@link CallIdentification}.
+     */
+    public void setCallIdentification(CallIdentification callIdentification) {
+        if (callIdentification != null) {
+            Log.addEvent(this, LogUtils.Events.CALL_IDENTIFICATION_SET,
+                    callIdentification.getCallScreeningPackageName());
+        }
+        mCallIdentification = callIdentification;
+
+        for (Listener l : mListeners) {
+            l.onCallIdentificationChanged(this);
+        }
+    }
+
+    /**
+     * @return Call identification returned by a {@link android.telecom.CallScreeningService}.
+     */
+    public CallIdentification getCallIdentification() {
+        return mCallIdentification;
+    }
 }
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 1d1a010..778c824 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -27,6 +27,7 @@
 import android.os.UserHandle;
 import android.os.PersistableBundle;
 import android.provider.CallLog.Calls;
+import android.telecom.CallIdentification;
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 import android.telecom.Log;
@@ -42,12 +43,8 @@
 import com.android.server.telecom.callfiltering.CallFilteringResult;
 
 import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
 import java.util.Locale;
 import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 /**
@@ -85,7 +82,8 @@
                 int features, PhoneAccountHandle accountHandle, long creationDate,
                 long durationInMillis, Long dataUsage, UserHandle initiatingUser, boolean isRead,
                 @Nullable LogCallCompletedListener logCallCompletedListener, int callBlockReason,
-                String callScreeningAppName, String callScreeningComponentName) {
+                String callScreeningAppName, String callScreeningComponentName,
+                CallIdentification callIdentification) {
             this.context = context;
             this.callerInfo = callerInfo;
             this.number = number;
@@ -104,6 +102,7 @@
             this.callBockReason = callBlockReason;
             this.callScreeningAppName = callScreeningAppName;
             this.callScreeningComponentName = callScreeningComponentName;
+            this.callIdentification = callIdentification;
         }
         // Since the members are accessed directly, we don't use the
         // mXxxx notation.
@@ -128,6 +127,8 @@
         public final int callBockReason;
         public final String callScreeningAppName;
         public final String callScreeningComponentName;
+
+        public final CallIdentification callIdentification;
     }
 
     private static final String TAG = CallLogManager.class.getSimpleName();
@@ -256,20 +257,22 @@
                         Connection.PROPERTY_ASSISTED_DIALING_USED,
                 call.wasEverRttCall());
 
+        CallIdentification callIdentification = call.getCallIdentification();
+
         if (callLogType == Calls.BLOCKED_TYPE) {
             logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber,
                     call.getHandlePresentation(), callLogType, callFeatures, accountHandle,
                     creationTime, age, callDataUsage, call.isEmergencyCall(),
                     call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener,
                     result.mCallBlockReason, result.mCallScreeningAppName,
-                    result.mCallScreeningComponentName);
+                    result.mCallScreeningComponentName, callIdentification);
         } else {
             logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber,
                     call.getHandlePresentation(), callLogType, callFeatures, accountHandle,
                     creationTime, age, callDataUsage, call.isEmergencyCall(),
                     call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener,
                     Calls.BLOCK_REASON_NOT_BLOCKED, null /*callScreeningAppName*/,
-                    null /*callScreeningComponentName*/);
+                    null /*callScreeningComponentName*/, callIdentification);
         }
     }
 
@@ -293,6 +296,8 @@
      * @param callBlockReason The reason why the call is blocked.
      * @param callScreeningAppName The call screening application name which block the call.
      * @param callScreeningComponentName The call screening component name which block the call.
+     * @param callIdentification Call identification information, if provided by a call screening
+     *                           service.
      */
     private void logCall(
             CallerInfo callerInfo,
@@ -312,7 +317,8 @@
             @Nullable LogCallCompletedListener logCallCompletedListener,
             int callBlockReason,
             String callScreeningAppName,
-            String callScreeningComponentName) {
+            String callScreeningComponentName,
+            @Nullable CallIdentification callIdentification) {
 
         // On some devices, to avoid accidental redialing of emergency numbers, we *never* log
         // emergency calls to the Call Log.  (This behavior is set on a per-product basis, based
@@ -346,7 +352,7 @@
             AddCallArgs args = new AddCallArgs(mContext, callerInfo, number, postDialDigits,
                     viaNumber, presentation, callType, features, accountHandle, start, duration,
                     dataUsage, initiatingUser, isRead, logCallCompletedListener, callBlockReason,
-                    callScreeningAppName, callScreeningComponentName);
+                    callScreeningAppName, callScreeningComponentName, callIdentification);
             logCallAsync(args);
         } else {
           Log.d(TAG, "Not adding emergency call to call log.");
@@ -508,7 +514,7 @@
                     c.presentation, c.callType, c.features, c.accountHandle, c.timestamp,
                     c.durationInSec, c.dataUsage, userToBeInserted == null,
                     userToBeInserted, c.isRead, c.callBockReason, c.callScreeningAppName,
-                    c.callScreeningComponentName);
+                    c.callScreeningComponentName, c.callIdentification);
         }
 
 
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index b02804d..cf5bf89 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -696,6 +696,11 @@
         public void onRemoteRttRequest(Call call, int requestId) {
             notifyRemoteRttRequest(call, requestId);
         }
+
+        @Override
+        public void onCallIdentificationChanged(Call call) {
+            updateCall(call);
+        }
     };
 
     private final SystemStateListener mSystemStateListener = new SystemStateListener() {
diff --git a/src/com/android/server/telecom/InCallTonePlayer.java b/src/com/android/server/telecom/InCallTonePlayer.java
index d0afe28..5864ce0 100644
--- a/src/com/android/server/telecom/InCallTonePlayer.java
+++ b/src/com/android/server/telecom/InCallTonePlayer.java
@@ -16,10 +16,13 @@
 
 package com.android.server.telecom;
 
+import android.annotation.Nullable;
+import android.content.Context;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.media.ToneGenerator;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.telecom.Log;
@@ -87,33 +90,51 @@
     public static class MediaPlayerAdapterImpl implements MediaPlayerAdapter {
         private MediaPlayer mMediaPlayer;
 
-        public MediaPlayerAdapterImpl(MediaPlayer mediaPlayer) {
+        /**
+         * Create new media player adapter backed by a real mediaplayer.
+         * Note: Its possible for the mediaplayer to be null if
+         * {@link MediaPlayer#create(Context, Uri)} fails for some reason; in this case we can
+         * continue but not bother playing the audio.
+         * @param mediaPlayer The media player.
+         */
+        public MediaPlayerAdapterImpl(@Nullable MediaPlayer mediaPlayer) {
             mMediaPlayer = mediaPlayer;
         }
 
         @Override
         public void setLooping(boolean isLooping) {
-            mMediaPlayer.setLooping(isLooping);
+            if (mMediaPlayer != null) {
+                mMediaPlayer.setLooping(isLooping);
+            }
         }
 
         @Override
         public void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) {
-            mMediaPlayer.setOnCompletionListener(listener);
+            if (mMediaPlayer != null) {
+                mMediaPlayer.setOnCompletionListener(listener);
+            }
         }
 
         @Override
         public void start() {
-            mMediaPlayer.start();
+            if (mMediaPlayer != null) {
+                mMediaPlayer.start();
+            }
         }
 
         @Override
         public void release() {
-            mMediaPlayer.release();
+            if (mMediaPlayer != null) {
+                mMediaPlayer.release();
+            }
         }
 
         @Override
         public int getDuration() {
-            return mMediaPlayer.getDuration();
+            if (mMediaPlayer != null) {
+                return mMediaPlayer.getDuration();
+            }
+            return 0;
         }
     }
 
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
index 0ebbd2b..bf8dba7 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -111,6 +111,7 @@
         public static final String CONTROLLER_SCREENING_COMPLETED =
                 "CONTROLLER_SCREENING_COMPLETED";
         public static final String SCREENING_COMPLETED = "SCREENING_COMPLETED";
+        public static final String CALL_IDENTIFICATION_SET = "CALL_IDENTIFICATION_SET";
         public static final String BLOCK_CHECK_INITIATED = "BLOCK_CHECK_INITIATED";
         public static final String BLOCK_CHECK_FINISHED = "BLOCK_CHECK_FINISHED";
         public static final String DIRECT_TO_VM_INITIATED = "DIRECT_TO_VM_INITIATED";
diff --git a/src/com/android/server/telecom/ParcelableCallUtils.java b/src/com/android/server/telecom/ParcelableCallUtils.java
index 925efae..fe52f4b 100644
--- a/src/com/android/server/telecom/ParcelableCallUtils.java
+++ b/src/com/android/server/telecom/ParcelableCallUtils.java
@@ -194,7 +194,8 @@
                 conferenceableCallIds,
                 call.getIntentExtras(),
                 call.getExtras(),
-                call.getCreationTimeMillis());
+                call.getCreationTimeMillis(),
+                call.getCallIdentification());
     }
 
     /**
@@ -241,7 +242,8 @@
                 Collections.emptyList(), /* conferenceableCallIds */
                 null, /* intentExtras */
                 null, /* callExtras */
-                call.getCreationTimeMillis());
+                call.getCreationTimeMillis(),
+                null /* callIdentification */);
     }
 
     private static int getParcelableState(Call call, boolean supportsExternalCalls) {
diff --git a/src/com/android/server/telecom/RoleManagerAdapterImpl.java b/src/com/android/server/telecom/RoleManagerAdapterImpl.java
index c912cc8..a53f475 100644
--- a/src/com/android/server/telecom/RoleManagerAdapterImpl.java
+++ b/src/com/android/server/telecom/RoleManagerAdapterImpl.java
@@ -27,11 +27,11 @@
 
 public class RoleManagerAdapterImpl implements RoleManagerAdapter {
     // TODO: replace with actual role manager const.
-    private static final String ROLE_CALL_REDIRECTION = "android.app.role.PROXY_CALLING_APP";
+    private static final String ROLE_CALL_REDIRECTION_APP = "android.app.role.PROXY_CALLING_APP";
     // TODO: replace with actual role manager const.
     private static final String ROLE_CAR_MODE_DIALER = "android.app.role.ROLE_CAR_MODE_DIALER";
     // TODO: replace with actual role manager const.
-    private static final String ROLE_CALL_SCREENING = "android.app.role.CALL_SCREENING";
+    private static final String ROLE_CALL_SCREENING = "android.app.role.CALL_SCREENING_APP";
     // TODO: replace with actual role manager const.
     private static final String ROLE_CALL_COMPANION_APP =
             "android.app.role.ROLE_CALL_COMPANION_APP";
@@ -105,11 +105,6 @@
         mCurrentUserHandle = currentUserHandle;
     }
 
-    private String getRoleManagerCallRedirectionApp() {
-        // TODO: Link in RoleManager
-        return null;
-    }
-
     private String getRoleManagerCallScreeningApp() {
         // TODO: Link in RoleManager
         return null;
@@ -125,6 +120,11 @@
         return Collections.emptyList();
     }
 
+    private String getRoleManagerCallRedirectionApp() {
+        // TODO: Link in RoleManager
+        return null;
+    }
+
     /**
      * Dumps the state of the {@link InCallController}.
      *
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 8e7303d..f57a0c6 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -58,7 +58,6 @@
 
 import com.android.internal.telecom.ITelecomService;
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.telecom.components.ChangeDefaultCallScreeningApp;
 import com.android.server.telecom.components.UserCallIntentProcessorFactory;
 import com.android.server.telecom.settings.BlockedNumbersActivity;
 
@@ -1346,147 +1345,6 @@
             }
         }
 
-        /**
-         * @see android.telecom.TelecomManager#requestChangeDefaultCallScreeningApp
-         */
-        @Override
-        public void requestChangeDefaultCallScreeningApp(ComponentName componentName, String
-            callingPackage) {
-            try {
-                Log.startSession("TSI.rCDCSA");
-                synchronized (mLock) {
-                    long token = Binder.clearCallingIdentity();
-                    try {
-                        if (callingPackage.equals(componentName.getPackageName())) {
-                            final Intent intent = new Intent(mContext,
-                                ChangeDefaultCallScreeningApp.class);
-                            intent.putExtra(
-                                TelecomManager.EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME,
-                                componentName.flattenToString());
-                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                            mContext.startActivity(intent);
-                        } else {
-                            throw new SecurityException(
-                                "calling package name does't match the package of the passed "
-                                    + "component name.");
-                        }
-                    } finally {
-                        Binder.restoreCallingIdentity(token);
-                    }
-                }
-            } finally {
-                Log.endSession();
-            }
-        }
-
-        /**
-         * @see android.telecom.TelecomManager#isDefaultCallScreeningApp
-         */
-        @Override
-        public boolean isDefaultCallScreeningApp(ComponentName componentName) {
-            try {
-                Log.startSession("TSI.iDCSA");
-                synchronized (mLock) {
-                    if (componentName == null) {
-                        return false;
-                    }
-                    mAppOpsManager
-                        .checkPackage(Binder.getCallingUid(), componentName.getPackageName());
-
-                    long token = Binder.clearCallingIdentity();
-                    try {
-                        final String defaultPackage = mSettingsSecureAdapter
-                            .getStringForUser(mContext.getContentResolver(),
-                                Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT,
-                                UserHandle.USER_CURRENT);
-
-                        if (!TextUtils.isEmpty(defaultPackage) && !TextUtils
-                            .isEmpty(componentName.flattenToString()) && TextUtils
-                            .equals(defaultPackage, componentName.flattenToString())) {
-                            return true;
-                        } else {
-                            Log.d(this,
-                                "Provided package name is not the current default Call Screening application.");
-                            return false;
-                        }
-                    } finally {
-                        Binder.restoreCallingIdentity(token);
-                    }
-                }
-            } finally {
-                Log.endSession();
-            }
-        }
-
-        /**
-         * @see android.telecom.TelecomManager#setDefaultCallScreeningApp
-         */
-        @Override
-        public void setDefaultCallScreeningApp(ComponentName componentName) {
-            try {
-                Log.startSession("TSI.sDCSA");
-                enforcePermission(MODIFY_PHONE_STATE);
-                enforcePermission(WRITE_SECURE_SETTINGS);
-                synchronized (mLock) {
-                    long token = Binder.clearCallingIdentity();
-                    try {
-                        try {
-                            mContext.getPackageManager().getApplicationInfo(
-                                componentName.getPackageName(), 0);
-                        } catch (PackageManager.NameNotFoundException e) {
-                            throw new IllegalArgumentException(
-                                "the specified package name does't exist componentName = " +
-                                    componentName);
-                        }
-
-                        Intent intent = new Intent(CallScreeningService.SERVICE_INTERFACE)
-                            .setPackage(componentName.getPackageName());
-                        List<ResolveInfo> entries = mContext.getPackageManager()
-                            .queryIntentServicesAsUser(intent, 0,
-                                mCallsManager.getCurrentUserHandle().getIdentifier());
-                        if (entries.isEmpty()) {
-                            throw new IllegalArgumentException(
-                                "The specified package name doesn't have call screening services");
-                        }
-
-                        try {
-                            ServiceInfo serviceInfo = mContext.getPackageManager().getServiceInfo(
-                                componentName, 0);
-                            if (!Manifest.permission.BIND_SCREENING_SERVICE.equals(serviceInfo
-                                .permission)) {
-                                throw new IllegalArgumentException(
-                                    "The passed component doesn't require " +
-                                        "BIND_SCREENING_SERVICE permission");
-                            }
-
-                        } catch (PackageManager.NameNotFoundException e) {
-                            throw new IllegalArgumentException(
-                                "the specified component name does't exist componentName = "
-                                    + componentName);
-                        }
-
-                        final String oldComponentName = mSettingsSecureAdapter
-                            .getStringForUser(mContext.getContentResolver(),
-                                Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT,
-                                UserHandle.USER_CURRENT);
-
-                        broadcastCallScreeningAppChangedIntent(oldComponentName, false);
-
-                        mSettingsSecureAdapter.putStringForUser(mContext.getContentResolver(),
-                            Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT,
-                            componentName.flattenToString(), UserHandle.USER_CURRENT);
-
-                        broadcastCallScreeningAppChangedIntent(componentName.flattenToString(),
-                            true);
-                    } finally {
-                        Binder.restoreCallingIdentity(token);
-                    }
-                }
-            } finally {
-                Log.endSession();
-            }
-        }
-
         @Override
         public TelecomAnalytics dumpCallAnalytics() {
             try {
diff --git a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
index 64e225a..b23cbe9 100644
--- a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
+++ b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
@@ -29,6 +29,7 @@
 import android.os.UserHandle;
 import android.provider.CallLog;
 import android.provider.Settings;
+import android.telecom.CallIdentification;
 import android.telecom.CallScreeningService;
 import android.telecom.Log;
 import android.telecom.ParcelableCall;
@@ -150,6 +151,25 @@
                 Log.endSession();
             }
         }
+
+        @Override
+        public void provideCallIdentification(String callId,
+                CallIdentification callIdentification) {
+            Log.startSession("CSCR.pCI");
+            long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mTelecomLock) {
+                    if (mCall != null && mCall.getId().equals(callId)) {
+                        callIdentification.setCallScreeningAppName(mAppName);
+                        callIdentification.setCallScreeningPackageName(mPackageName);
+                        mCall.setCallIdentification(callIdentification);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+                Log.endSession();
+            }
+        }
     }
 
     private final Context mContext;
diff --git a/src/com/android/server/telecom/components/ChangeDefaultCallScreeningApp.java b/src/com/android/server/telecom/components/ChangeDefaultCallScreeningApp.java
deleted file mode 100644
index a88c7d1..0000000
--- a/src/com/android/server/telecom/components/ChangeDefaultCallScreeningApp.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.telecom.components;
-
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
-import com.android.server.telecom.R;
-
-import android.content.ComponentName;
-import android.content.DialogInterface;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.telecom.Log;
-import android.telecom.TelecomManager;
-import android.text.TextUtils;
-
-public class ChangeDefaultCallScreeningApp extends AlertActivity implements
-        DialogInterface.OnClickListener {
-
-    private static final String TAG = ChangeDefaultCallScreeningApp.class.getSimpleName();
-    private ComponentName mNewComponentName;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mNewComponentName = ComponentName.unflattenFromString(getIntent().getStringExtra(
-            TelecomManager.EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME));
-
-        if (canChangeDefaultCallScreening()) {
-            buildDialog();
-        } else {
-            finish();
-        }
-    }
-
-    @Override
-    public void onClick(DialogInterface dialog, int which) {
-        switch (which) {
-            case BUTTON_POSITIVE:
-                try {
-                    TelecomManager.from(this).setDefaultCallScreeningApp(mNewComponentName);
-                } catch (IllegalArgumentException e) {
-                    Log.e(TAG, e, e.getMessage());
-                    break;
-                }
-                break;
-            case BUTTON_NEGATIVE:
-                break;
-        }
-    }
-
-    private boolean canChangeDefaultCallScreening() {
-        boolean canChange;
-        String defaultComponentName = Settings.Secure
-            .getStringForUser(getApplicationContext().getContentResolver(),
-                Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT, UserHandle.USER_CURRENT);
-
-        ComponentName oldComponentName = TextUtils.isEmpty(defaultComponentName) ? null
-            : ComponentName.unflattenFromString(defaultComponentName);
-
-        canChange = oldComponentName == null || !oldComponentName.getPackageName()
-            .equals(mNewComponentName.getPackageName()) || !oldComponentName.flattenToString()
-            .equals(mNewComponentName.flattenToString());
-
-        return canChange;
-    }
-
-    private void buildDialog() {
-        final String newPackageLabel = getApplicationLabel(mNewComponentName);
-        final AlertController.AlertParams p = mAlertParams;
-
-        p.mTitle = getString(R.string.change_default_call_screening_dialog_title, newPackageLabel);
-        p.mMessage = getDialogBody(newPackageLabel);
-        p.mPositiveButtonText = getString(
-            R.string.change_default_call_screening_dialog_affirmative);
-        p.mNegativeButtonText = getString(R.string.change_default_call_screening_dialog_negative);
-        p.mPositiveButtonListener = this;
-        p.mNegativeButtonListener = this;
-
-        setupAlert();
-    }
-
-    private String getDialogBody(String newPackageLabel) {
-        final String oldPackage = Settings.Secure.getStringForUser(
-            getApplicationContext().getContentResolver(),
-            Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT, UserHandle.USER_CURRENT);
-        ComponentName oldPackageComponentName = null;
-        if (!TextUtils.isEmpty(oldPackage)) {
-            oldPackageComponentName = ComponentName.unflattenFromString(oldPackage);
-        }
-
-        String dialogBody = getString(R.string.change_default_call_screening_warning_message,
-            newPackageLabel);
-
-        if (oldPackageComponentName != null) {
-            dialogBody = getString(
-                R.string.change_default_call_screening_warning_message_for_disable_old_app,
-                getApplicationLabel(oldPackageComponentName)) + " "
-                + dialogBody;
-        }
-
-        return dialogBody;
-    }
-
-    /**
-     * Returns the application label that corresponds to the given package name
-     *
-     * @return Application label for the given package name, or null if not found.
-     */
-    private String getApplicationLabel(ComponentName componentName) {
-        final PackageManager pm = getPackageManager();
-
-        try {
-            ApplicationInfo info = pm.getApplicationInfo(componentName.getPackageName(), 0);
-            return pm.getApplicationLabel(info).toString();
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(TAG, "Application info not found for packageName " + componentName
-                .getPackageName());
-        }
-
-        return componentName.getPackageName();
-    }
-}
diff --git a/testapps/res/layout/call_list_item.xml b/testapps/res/layout/call_list_item.xml
index c9f2ff7..ecaa237 100644
--- a/testapps/res/layout/call_list_item.xml
+++ b/testapps/res/layout/call_list_item.xml
@@ -39,4 +39,37 @@
             android:layout_height="wrap_content"
             android:textSize="25dp"
             android:text="TextView" />
+    <ImageView
+        android:id="@+id/callIdPhoto"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+    <TextView
+        android:id="@+id/callIdName"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="25dp"
+        android:text="TextView" />
+    <TextView
+        android:id="@+id/callIdDescription"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="25dp"
+        android:text="TextView" />
+    <TextView
+        android:id="@+id/callIdDetails"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="25dp"
+        android:text="TextView" />
+    <TextView
+        android:id="@+id/callIdType"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="25dp"
+        android:text="TextView" />
 </LinearLayout>
diff --git a/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java b/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java
index 85785d5..e5b8780 100644
--- a/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java
+++ b/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java
@@ -18,13 +18,16 @@
 
 import android.content.Context;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.telecom.Call;
+import android.telecom.CallIdentification;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
+import android.widget.ImageView;
 import android.widget.TextView;
 
 public class CallListAdapter extends BaseAdapter {
@@ -90,9 +93,14 @@
             convertView = mLayoutInflater.inflate(R.layout.call_list_item, parent, false);
         }
 
-        TextView phoneNumber = (TextView) convertView.findViewById(R.id.phoneNumber);
-        TextView duration = (TextView) convertView.findViewById(R.id.duration);
-        TextView state = (TextView) convertView.findViewById(R.id.callState);
+        TextView phoneNumber = convertView.findViewById(R.id.phoneNumber);
+        TextView duration = convertView.findViewById(R.id.duration);
+        TextView state = convertView.findViewById(R.id.callState);
+        TextView callIdName = convertView.findViewById(R.id.callIdName);
+        TextView callIdDescription = convertView.findViewById(R.id.callIdDescription);
+        TextView callIdDetails = convertView.findViewById(R.id.callIdDetails);
+        TextView callIdType = convertView.findViewById(R.id.callIdType);
+        ImageView callIdPhoto = convertView.findViewById(R.id.callIdPhoto);
 
         Call call = mCallList.getCall(position);
         Uri handle = call.getDetails().getHandle();
@@ -103,12 +111,36 @@
 
         state.setText(getStateString(call));
 
+        CallIdentification callIdentification = call.getDetails().getCallIdentification();
+        if (callIdentification != null) {
+            callIdName.setText(callIdentification.getName());
+            callIdDescription.setText(callIdentification.getDescription());
+            callIdDetails.setText(callIdentification.getDetails());
+            callIdType.setText("Call Type: " + callIdentification.getNuisanceConfidence());
+            callIdPhoto.setImageIcon(callIdentification.getPhoto());
+        }
+
         Log.i(TAG, "Call found: " + ((handle == null) ? "null" : handle.getSchemeSpecificPart())
                 + ", " + durationMs);
+        Log.i(TAG, "Call extras: " + extrasToString(call.getDetails().getExtras()));
+        Log.i(TAG, "Call intent extras: " + extrasToString(call.getDetails().getIntentExtras()));
+
 
         return convertView;
     }
 
+    private String extrasToString(Bundle bundle) {
+        StringBuilder sb = new StringBuilder("[");
+        for (String key : bundle.keySet()) {
+            sb.append(key);
+            sb.append(": ");
+            sb.append(bundle.get(key));
+            sb.append("\n");
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+
     private static String getStateString(Call call) {
         switch (call.getState()) {
             case Call.STATE_ACTIVE:
diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java b/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
index 81a469e..fb231da 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
@@ -17,7 +17,9 @@
 package com.android.server.telecom.testapps;
 
 import android.content.Intent;
+import android.graphics.drawable.Icon;
 import android.telecom.Call;
+import android.telecom.CallIdentification;
 import android.telecom.CallScreeningService;
 import android.telecom.Log;
 
@@ -56,6 +58,15 @@
     }
 
     public void allowCall() {
+        // Provide call identification
+        CallIdentification callIdentification = new CallIdentification.Builder()
+                .setNuisanceConfidence(CallIdentification.CONFIDENCE_NOT_NUISANCE)
+                .setName("Joe's Laundry")
+                .setDescription("1234 DirtySocks Lane")
+                .setDetails("Open 24 hrs")
+                .setPhoto(Icon.createWithResource(this, R.drawable.ic_android_black_24dp))
+                .build();
+        provideCallIdentification(mDetails, callIdentification);
         CallScreeningService.CallResponse
                 response = new CallScreeningService.CallResponse.Builder()
                 .setDisallowCall(false)
diff --git a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
index 0fc6666..2b65e07 100644
--- a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
@@ -25,11 +25,13 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.graphics.drawable.Icon;
 import android.os.IBinder;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.CallLog;
+import android.telecom.CallIdentification;
 import android.telecom.CallScreeningService;
 import android.telecom.ParcelableCall;
 import android.telecom.TelecomManager;
@@ -313,6 +315,37 @@
         )), eq(USER_CHOSEN_CALL_SCREENING.getPackageName()));
     }
 
+    /**
+     * Verify that call identification information provided via a {@link CallScreeningService} is
+     * propagated to the Telecom call.
+     * @throws Exception
+     */
+    @SmallTest
+    @Test
+    public void testProvideCallIdentification() throws Exception {
+        mResolveInfo.serviceInfo.packageName = USER_CHOSEN_CALL_SCREENING.getPackageName();
+        mResolveInfo.serviceInfo.name = USER_CHOSEN_CALL_SCREENING.getClassName();
+        when(TelecomManager.from(mContext)).thenReturn(mTelecomManager);
+        when(mTelecomManager.getDefaultDialerPackage()).thenReturn(DEFAULT_DIALER_PACKAGE);
+
+        mFilter.startCallScreeningFilter(mCall, mCallback,
+                USER_CHOSEN_CALL_SCREENING.getPackageName(),
+                USER_CHOSEN_CALL_SCREENING_APP_NAME);
+        ServiceConnection serviceConnection = verifyBindingIntent();
+        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
+        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
+
+        CallIdentification callIdentification = new CallIdentification.Builder()
+                .setNuisanceConfidence(CallIdentification.CONFIDENCE_NOT_NUISANCE)
+                .setName("Joe's Laundry")
+                .setDescription("1234 DirtySocks Lane")
+                .setDetails("Open 24 hrs")
+                .build();
+        csAdapter.provideCallIdentification(CALL_ID, callIdentification);
+
+        verify(mCall).setCallIdentification(eq(callIdentification));
+    }
+
     private ServiceConnection verifyBindingIntent() {
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         ArgumentCaptor<ServiceConnection> serviceCaptor =
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index a459aac..c11811d 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -764,80 +764,6 @@
 
     @SmallTest
     @Test
-    public void testRequestChangeDefaultCallScreeningAppCallingPackageMatchComponentName()
-            throws Exception {
-        String callingPackage = "com.android.thirdparty";
-
-        doNothing().when(mContext).startActivity(any(Intent.class));
-
-        mTSIBinder.requestChangeDefaultCallScreeningApp(THIRD_PARTY_CALL_SCREENING,
-                callingPackage);
-
-        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mContext, times(1)).startActivity(intentCaptor.capture());
-
-        Intent capturedIntent = intentCaptor.getValue();
-        String className = capturedIntent.getComponent().getClassName();
-        assertEquals(className,
-                "com.android.server.telecom.components.ChangeDefaultCallScreeningApp");
-
-        String packageNameExtra = capturedIntent.getStringExtra(
-                TelecomManager.EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME);
-        assertEquals(packageNameExtra, THIRD_PARTY_CALL_SCREENING.flattenToString());
-    }
-
-    @SmallTest
-    @Test
-    public void testRequestChangeDefaultCallScreeningAppCallingPackageNoMatchComponentName()
-        throws Exception {
-        boolean exceptionThrown = false;
-        String callingPackage = "com.android.unknown";
-
-        try {
-            mTSIBinder
-                .requestChangeDefaultCallScreeningApp(THIRD_PARTY_CALL_SCREENING, callingPackage);
-        } catch (SecurityException e) {
-            exceptionThrown = true;
-        }
-
-        assertTrue(exceptionThrown);
-    }
-
-    @SmallTest
-    @Test
-    public void testIsDefaultCallScreeningApp() throws Exception {
-        doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString());
-        assertTrue(mTSIBinder.isDefaultCallScreeningApp(THIRD_PARTY_CALL_SCREENING));
-    }
-
-    @SmallTest
-    @Test
-    public void testIsDefaultCallScreeningAppFailure() throws Exception {
-        ComponentName unknownComponentName = new ComponentName("com.android.unknown",
-            "com.android.unknown.callscreeningserviceimpl");
-        assertFalse(mTSIBinder.isDefaultCallScreeningApp(unknownComponentName));
-    }
-
-    @SmallTest
-    @Test
-    public void testSetDefaultCallScreeningAppSpecifiedComponentNameNoExist() throws Exception {
-        boolean exceptionThrown = false;
-
-        when(mContext.getPackageManager()
-            .getApplicationInfo(THIRD_PARTY_CALL_SCREENING.getPackageName(), 0))
-            .thenThrow(new IllegalArgumentException());
-
-        try {
-            mTSIBinder.setDefaultCallScreeningApp(THIRD_PARTY_CALL_SCREENING);
-        } catch (IllegalArgumentException e) {
-            exceptionThrown = true;
-        }
-
-        assertTrue(exceptionThrown);
-    }
-
-    @SmallTest
-    @Test
     public void testSetDefaultDialerNoModifyPhoneStatePermission() throws Exception {
         doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                 eq(MODIFY_PHONE_STATE), nullable(String.class));