1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.appcloning.contacts; 18 19 import java.util.List; 20 21 public class ContactsShellCommandHelper { 22 23 private static final String CONTACTS_AUTHORITY_ENDPOINT = "content://com.android.contacts/"; 24 private static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter"; 25 private static final String URI_TAG = "--uri"; 26 private static final String BIND_TAG = "--bind"; 27 private static final String USER_TAG = "--user"; 28 private static final String WHERE_CLAUSE_TAG = "--where"; 29 30 private enum ContentOperationType { 31 INSERT("insert"), 32 DELETE("delete"), 33 QUERY("query"), 34 UPDATE("update"); 35 36 public final String operation; ContentOperationType(String s)37 ContentOperationType(String s) { 38 this.operation = s; 39 } 40 } 41 42 public static class ColumnBindings { 43 public final String columnName; 44 public final String columnValue; 45 public final Type columnType; 46 47 enum Type { 48 STRING("s"), 49 INT("i"), 50 FLOAT("f"), 51 LONG("l"), 52 DOUBLE("d"); 53 54 public final String charValue; 55 Type(String s)56 Type(String s) { 57 this.charValue = s; 58 } 59 } 60 ColumnBindings(String name, String value, Type type)61 public ColumnBindings(String name, String value, Type type) { 62 this.columnType = type; 63 this.columnName = name; 64 this.columnValue = value; 65 } 66 } 67 68 /** 69 * Helper method that builds shell command for the content insert operation corresponding to the 70 * input values 71 * @param endpoint Contacts endpoint that the uri would access 72 * @param bindings Content values and the column name to which they should be bound 73 * @param user user identifier to redirect to the correct content provider 74 * @return String corresponding to the content insert shell command 75 */ getInsertTestContactCommand(String endpoint, List<ColumnBindings> bindings, String user)76 public static String getInsertTestContactCommand(String endpoint, List<ColumnBindings> bindings, 77 String user) { 78 return buildContentOperationCommand(ContentOperationType.INSERT.operation, endpoint, 79 /* callerIsSyncAdapter */false, bindings, /* whereOperation */ null, user); 80 } 81 82 /** 83 * Helper method that builds shell command for the content delete operation corresponding to the 84 * input values 85 * @param endpoint Contacts endpoint that the uri would access 86 * @param whereClause String that specifies the where clause to identify the rows that the 87 * query will be run on 88 * @param user user identifier to redirect to the correct content provider 89 * @return String corresponding to the content delete shell command 90 */ getDeleteContactCommand(String endpoint, String whereClause, String user)91 public static String getDeleteContactCommand(String endpoint, String whereClause, String user) { 92 return buildContentOperationCommand(ContentOperationType.DELETE.operation, endpoint, 93 /* callerIsSyncAdapter */ true, /* bindValues */ null, whereClause, user); 94 } 95 96 /** 97 * 98 * @param endpoint Contacts endpoint that the uri would access 99 * @param whereClause String that specifies the where clause to identify the rows that the 100 * query will be run on 101 * @param user user identifier to redirect to the correct content provider 102 * @return String corresponding to the content query shell command 103 * @return 104 */ getQueryTestContactsCommand(String endpoint, String whereClause, String user)105 public static String getQueryTestContactsCommand(String endpoint, String whereClause, 106 String user) { 107 return buildContentOperationCommand(ContentOperationType.QUERY.operation, endpoint, 108 /* callerIsSyncAdapter */ false, /* bindValues */ null, whereClause, user); 109 } 110 111 /** 112 * A helper method that builds the shell command for a content operation 113 * @param operationType content operation type - insert/delete/query/update 114 * @param endpoint Contacts endpoint that the uri would access 115 * @param callerIsSyncAdapter boolean value indicating if caller is a sync adapter 116 * @param bindValues Content values and the column name to which they should be bound 117 * @param whereOperations String that specifies the where clause to identify the rows that the 118 * query will be run on 119 * @param user user identifier to redirect to the correct content provider 120 */ buildContentOperationCommand(String operationType, String endpoint, boolean callerIsSyncAdapter, List<ColumnBindings> bindValues, String whereOperations, String user)121 private static String buildContentOperationCommand(String operationType, 122 String endpoint, boolean callerIsSyncAdapter, 123 List<ColumnBindings> bindValues, String whereOperations, 124 String user) { 125 if (operationType == null || endpoint == null) { 126 return null; 127 } 128 129 String contentOperation = "content " + operationType; 130 131 // Build the uri part of the command 132 StringBuilder uriPart = new StringBuilder(); 133 uriPart.append(URI_TAG).append(" ") 134 .append(CONTACTS_AUTHORITY_ENDPOINT) 135 .append(endpoint); 136 if (callerIsSyncAdapter) { 137 uriPart.append("?") 138 .append(CALLER_IS_SYNCADAPTER) 139 .append("=true"); 140 } 141 142 // Build the column to value bindings part of the command 143 StringBuilder bindingsString = new StringBuilder(); 144 if (bindValues != null && !bindValues.isEmpty()) { 145 for (ColumnBindings binding: bindValues) { 146 bindingsString.append(BIND_TAG).append(" ") 147 .append(binding.columnName) 148 .append(":") 149 .append(binding.columnType.charValue) 150 .append(":") 151 .append(binding.columnValue) 152 .append(" "); 153 } 154 } 155 156 // Build the where clause of the command 157 StringBuilder where = new StringBuilder(); 158 if (whereOperations != null) { 159 where.append(WHERE_CLAUSE_TAG).append(" ") 160 .append(whereOperations); 161 } 162 163 // Build user part of the command if user id is provided 164 StringBuilder userPart = new StringBuilder(); 165 if (user != null) { 166 userPart.append(USER_TAG).append(" ") 167 .append(user); 168 } 169 return contentOperation + " " + uriPart + " " + bindingsString + " " + where + " " 170 + userPart; 171 } 172 } 173