diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 6a5d857c4a37e..e7c4a075cf728 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -38,6 +38,7 @@ import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; +import android.util.Log; import com.android.internal.telephony.CallerInfo; import com.android.internal.telephony.PhoneConstants; @@ -49,6 +50,7 @@ import java.util.List; */ public class CallLog { private static final String LOG_TAG = "CallLog"; + private static final boolean VERBOSE_LOG = false; // DON'T SUBMIT WITH TRUE. public static final String AUTHORITY = "call_log"; @@ -58,6 +60,17 @@ public class CallLog { public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); + + /** + * The "shadow" provider stores calllog when the real calllog provider is encrypted. The + * real provider will alter copy from it when it starts, and remove the entries in the shadow. + * + *
See the comment in {@link Calls#addCall} for the details.
+ *
+ * @hide
+ */
+ public static final String SHADOW_AUTHORITY = "call_log_shadow";
+
/**
* Contains the recent calls.
*/
@@ -68,6 +81,10 @@ public class CallLog {
public static final Uri CONTENT_URI =
Uri.parse("content://call_log/calls");
+ /** @hide */
+ public static final Uri SHADOW_CONTENT_URI =
+ Uri.parse("content://call_log_shadow/calls");
+
/**
* The content:// style URL for filtering this table on phone numbers
*/
@@ -458,8 +475,10 @@ public class CallLog {
public static Uri addCall(CallerInfo ci, Context context, String number,
int presentation, int callType, int features, PhoneAccountHandle accountHandle,
long start, int duration, Long dataUsage) {
- return addCall(ci, context, number, "", presentation, callType, features, accountHandle,
- start, duration, dataUsage, false, null, false);
+ return addCall(ci, context, number, /* postDialDigits =*/ "", presentation,
+ callType, features, accountHandle,
+ start, duration, dataUsage, /* addForAllUsers =*/ false,
+ /* userToBeInsertedTo =*/ null, /* is_read =*/ false);
}
@@ -495,7 +514,7 @@ public class CallLog {
boolean addForAllUsers, UserHandle userToBeInsertedTo) {
return addCall(ci, context, number, postDialDigits, presentation, callType, features,
accountHandle, start, duration, dataUsage, addForAllUsers, userToBeInsertedTo,
- false);
+ /* is_read =*/ false);
}
/**
@@ -526,13 +545,18 @@ public class CallLog {
* Used for call log restore of missed calls.
*
* @result The URI of the call log entry belonging to the user that made or received this
- * call.
+ * call. This could be of the shadow provider. Do not return it to non-system apps,
+ * as they don't have permissions.
* {@hide}
*/
public static Uri addCall(CallerInfo ci, Context context, String number,
String postDialDigits, int presentation, int callType, int features,
PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage,
boolean addForAllUsers, UserHandle userToBeInsertedTo, boolean is_read) {
+ if (VERBOSE_LOG) {
+ Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s",
+ number, userToBeInsertedTo, addForAllUsers));
+ }
final ContentResolver resolver = context.getContentResolver();
int numberPresentation = PRESENTATION_ALLOWED;
@@ -647,41 +671,104 @@ public class CallLog {
}
}
+ /*
+ Writing the calllog works in the following way:
+ - All user entries
+ - if user-0 is encrypted, insert to user-0's shadow only.
+ (other users should also be encrypted, so nothing to do for other users.)
+ - if user-0 is decrypted, insert to user-0's real provider, as well as
+ all other users that are running and decrypted and should have calllog.
+
+ - Single user entry.
+ - If the target user is encryted, insert to its shadow.
+ - Otherwise insert to its real provider.
+
+ When the (real) calllog provider starts, it copies entries that it missed from
+ elsewhere.
+ - When user-0's (real) provider starts, it copies from user-0's shadow, and clears
+ the shadow.
+
+ - When other users (real) providers start, unless it shouldn't have calllog entries,
+ - Copy from the user's shadow, and clears the shadow.
+ - Copy from user-0's entries that are FOR_ALL_USERS = 1. (and don't clear it.)
+ */
+
Uri result = null;
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ final int currentUserId = userManager.getUserHandle();
+
if (addForAllUsers) {
- // Insert the entry for all currently running users, in order to trigger any
- // ContentObservers currently set on the call log.
- final UserManager userManager = (UserManager) context.getSystemService(
- Context.USER_SERVICE);
- List