1/* 2 * Copyright (C) 2014 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#include "Rule.h" 18 19#include <utils/String8.h> 20 21using namespace android; 22 23namespace split { 24 25inline static void indentStr(String8& str, int indent) { 26 while (indent > 0) { 27 str.append(" "); 28 indent--; 29 } 30} 31 32Rule::Rule(const Rule& rhs) 33 : RefBase() 34 , op(rhs.op) 35 , key(rhs.key) 36 , negate(rhs.negate) 37 , stringArgs(rhs.stringArgs) 38 , longArgs(rhs.longArgs) 39 , subrules(rhs.subrules) { 40} 41 42String8 Rule::toJson(int indent) const { 43 String8 str; 44 indentStr(str, indent); 45 str.append("{\n"); 46 indent++; 47 indentStr(str, indent); 48 str.append("\"op\": \""); 49 switch (op) { 50 case ALWAYS_TRUE: 51 str.append("ALWAYS_TRUE"); 52 break; 53 case GREATER_THAN: 54 str.append("GREATER_THAN"); 55 break; 56 case LESS_THAN: 57 str.append("LESS_THAN"); 58 break; 59 case EQUALS: 60 str.append("EQUALS"); 61 break; 62 case AND_SUBRULES: 63 str.append("AND_SUBRULES"); 64 break; 65 case OR_SUBRULES: 66 str.append("OR_SUBRULES"); 67 break; 68 case CONTAINS_ANY: 69 str.append("CONTAINS_ANY"); 70 break; 71 default: 72 str.appendFormat("%d", op); 73 break; 74 } 75 str.append("\""); 76 77 if (negate) { 78 str.append(",\n"); 79 indentStr(str, indent); 80 str.append("\"negate\": true"); 81 } 82 83 bool includeKey = true; 84 switch (op) { 85 case AND_SUBRULES: 86 case OR_SUBRULES: 87 includeKey = false; 88 break; 89 default: 90 break; 91 } 92 93 if (includeKey) { 94 str.append(",\n"); 95 indentStr(str, indent); 96 str.append("\"property\": \""); 97 switch (key) { 98 case NONE: 99 str.append("NONE"); 100 break; 101 case SDK_VERSION: 102 str.append("SDK_VERSION"); 103 break; 104 case SCREEN_DENSITY: 105 str.append("SCREEN_DENSITY"); 106 break; 107 case NATIVE_PLATFORM: 108 str.append("NATIVE_PLATFORM"); 109 break; 110 case LANGUAGE: 111 str.append("LANGUAGE"); 112 break; 113 default: 114 str.appendFormat("%d", key); 115 break; 116 } 117 str.append("\""); 118 } 119 120 if (op == AND_SUBRULES || op == OR_SUBRULES) { 121 str.append(",\n"); 122 indentStr(str, indent); 123 str.append("\"subrules\": [\n"); 124 const size_t subruleCount = subrules.size(); 125 for (size_t i = 0; i < subruleCount; i++) { 126 str.append(subrules[i]->toJson(indent + 1)); 127 if (i != subruleCount - 1) { 128 str.append(","); 129 } 130 str.append("\n"); 131 } 132 indentStr(str, indent); 133 str.append("]"); 134 } else { 135 switch (key) { 136 case SDK_VERSION: 137 case SCREEN_DENSITY: { 138 str.append(",\n"); 139 indentStr(str, indent); 140 str.append("\"args\": ["); 141 const size_t argCount = longArgs.size(); 142 for (size_t i = 0; i < argCount; i++) { 143 if (i != 0) { 144 str.append(", "); 145 } 146 str.appendFormat("%d", longArgs[i]); 147 } 148 str.append("]"); 149 break; 150 } 151 case LANGUAGE: 152 case NATIVE_PLATFORM: { 153 str.append(",\n"); 154 indentStr(str, indent); 155 str.append("\"args\": ["); 156 const size_t argCount = stringArgs.size(); 157 for (size_t i = 0; i < argCount; i++) { 158 if (i != 0) { 159 str.append(", "); 160 } 161 str.append(stringArgs[i]); 162 } 163 str.append("]"); 164 break; 165 } 166 default: 167 break; 168 } 169 } 170 str.append("\n"); 171 indent--; 172 indentStr(str, indent); 173 str.append("}"); 174 return str; 175} 176 177sp<Rule> Rule::simplify(sp<Rule> rule) { 178 if (rule->op != AND_SUBRULES && rule->op != OR_SUBRULES) { 179 return rule; 180 } 181 182 Vector<sp<Rule> > newSubrules; 183 newSubrules.setCapacity(rule->subrules.size()); 184 const size_t subruleCount = rule->subrules.size(); 185 for (size_t i = 0; i < subruleCount; i++) { 186 sp<Rule> simplifiedRule = simplify(rule->subrules.editItemAt(i)); 187 if (simplifiedRule != NULL) { 188 if (simplifiedRule->op == rule->op) { 189 newSubrules.appendVector(simplifiedRule->subrules); 190 } else { 191 newSubrules.add(simplifiedRule); 192 } 193 } 194 } 195 196 const size_t newSubruleCount = newSubrules.size(); 197 if (newSubruleCount == 0) { 198 return NULL; 199 } else if (subruleCount == 1) { 200 return newSubrules.editTop(); 201 } 202 rule->subrules = newSubrules; 203 return rule; 204} 205 206} // namespace split 207