1 /* 2 * Copyright (C) 2024 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 package android.widget; 17 18 import static com.android.text.flags.Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN; 19 import static com.android.text.flags.Flags.noBreakNoHyphenationSpan; 20 21 import static java.nio.charset.StandardCharsets.UTF_8; 22 23 import android.annotation.FlaggedApi; 24 import android.content.res.ColorStateList; 25 import android.content.res.Resources; 26 import android.graphics.Bitmap; 27 import android.graphics.BitmapFactory; 28 import android.graphics.BlendMode; 29 import android.graphics.drawable.Icon; 30 import android.graphics.text.LineBreakConfig; 31 import android.os.LocaleList; 32 import android.os.PersistableBundle; 33 import android.text.Annotation; 34 import android.text.Layout; 35 import android.text.SpannableStringBuilder; 36 import android.text.Spanned; 37 import android.text.style.AbsoluteSizeSpan; 38 import android.text.style.AccessibilityClickableSpan; 39 import android.text.style.AccessibilityReplacementSpan; 40 import android.text.style.AccessibilityURLSpan; 41 import android.text.style.AlignmentSpan; 42 import android.text.style.BackgroundColorSpan; 43 import android.text.style.BulletSpan; 44 import android.text.style.CharacterStyle; 45 import android.text.style.EasyEditSpan; 46 import android.text.style.ForegroundColorSpan; 47 import android.text.style.LeadingMarginSpan; 48 import android.text.style.LineBackgroundSpan; 49 import android.text.style.LineBreakConfigSpan; 50 import android.text.style.LineHeightSpan; 51 import android.text.style.LocaleSpan; 52 import android.text.style.QuoteSpan; 53 import android.text.style.RelativeSizeSpan; 54 import android.text.style.ScaleXSpan; 55 import android.text.style.SpellCheckSpan; 56 import android.text.style.StrikethroughSpan; 57 import android.text.style.StyleSpan; 58 import android.text.style.SubscriptSpan; 59 import android.text.style.SuggestionRangeSpan; 60 import android.text.style.SuggestionSpan; 61 import android.text.style.SuperscriptSpan; 62 import android.text.style.TextAppearanceSpan; 63 import android.text.style.TtsSpan; 64 import android.text.style.TypefaceSpan; 65 import android.text.style.URLSpan; 66 import android.text.style.UnderlineSpan; 67 import android.util.Log; 68 import android.util.LongSparseArray; 69 import android.util.proto.ProtoInputStream; 70 import android.util.proto.ProtoOutputStream; 71 import android.util.proto.ProtoUtils; 72 73 import androidx.annotation.NonNull; 74 75 import java.io.ByteArrayInputStream; 76 import java.io.ByteArrayOutputStream; 77 import java.io.IOException; 78 import java.util.ArrayList; 79 import java.util.List; 80 import java.util.function.Function; 81 82 /** 83 * This class provides serialization for certain types used within RemoteViews. 84 * 85 * @hide 86 */ 87 public class RemoteViewsSerializers { 88 private static final String TAG = "RemoteViews"; 89 90 /** 91 * Write Icon to proto. 92 */ writeIconToProto(@onNull ProtoOutputStream out, @NonNull Resources appResources, @NonNull Icon icon)93 public static void writeIconToProto(@NonNull ProtoOutputStream out, 94 @NonNull Resources appResources, @NonNull Icon icon) { 95 if (icon.getTintList() != null) { 96 final long token = out.start(RemoteViewsProto.Icon.TINT_LIST); 97 icon.getTintList().writeToProto(out); 98 out.end(token); 99 } 100 out.write(RemoteViewsProto.Icon.BLEND_MODE, BlendMode.toValue(icon.getTintBlendMode())); 101 switch (icon.getType()) { 102 case Icon.TYPE_BITMAP: 103 final ByteArrayOutputStream bitmapBytes = new ByteArrayOutputStream(); 104 icon.getBitmap().compress(Bitmap.CompressFormat.WEBP_LOSSLESS, 100, bitmapBytes); 105 out.write(RemoteViewsProto.Icon.BITMAP, bitmapBytes.toByteArray()); 106 break; 107 case Icon.TYPE_ADAPTIVE_BITMAP: 108 final ByteArrayOutputStream adaptiveBitmapBytes = new ByteArrayOutputStream(); 109 icon.getBitmap() 110 .compress(Bitmap.CompressFormat.WEBP_LOSSLESS, 100, adaptiveBitmapBytes); 111 out.write(RemoteViewsProto.Icon.ADAPTIVE_BITMAP, adaptiveBitmapBytes.toByteArray()); 112 break; 113 case Icon.TYPE_RESOURCE: 114 out.write( 115 RemoteViewsProto.Icon.RESOURCE, 116 appResources.getResourceName(icon.getResId())); 117 break; 118 case Icon.TYPE_DATA: 119 out.write(RemoteViewsProto.Icon.DATA, icon.getDataBytes()); 120 break; 121 case Icon.TYPE_URI: 122 out.write(RemoteViewsProto.Icon.URI, icon.getUriString()); 123 break; 124 case Icon.TYPE_URI_ADAPTIVE_BITMAP: 125 out.write(RemoteViewsProto.Icon.URI_ADAPTIVE_BITMAP, icon.getUriString()); 126 break; 127 default: 128 Log.e(TAG, "Tried to serialize unknown Icon type " + icon.getType()); 129 } 130 } 131 132 /** 133 * Create Icon from proto. 134 */ 135 @NonNull createIconFromProto(@onNull ProtoInputStream in)136 public static Function<Resources, Icon> createIconFromProto(@NonNull ProtoInputStream in) 137 throws Exception { 138 final LongSparseArray<Object> values = new LongSparseArray<>(); 139 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 140 switch (in.getFieldNumber()) { 141 case (int) RemoteViewsProto.Icon.BLEND_MODE: 142 values.put( 143 RemoteViewsProto.Icon.BLEND_MODE, 144 in.readInt(RemoteViewsProto.Icon.BLEND_MODE)); 145 break; 146 case (int) RemoteViewsProto.Icon.TINT_LIST: 147 final long tintListToken = in.start(RemoteViewsProto.Icon.TINT_LIST); 148 values.put(RemoteViewsProto.Icon.TINT_LIST, ColorStateList.createFromProto(in)); 149 in.end(tintListToken); 150 break; 151 case (int) RemoteViewsProto.Icon.BITMAP: 152 byte[] bitmapData = in.readBytes(RemoteViewsProto.Icon.BITMAP); 153 values.put( 154 RemoteViewsProto.Icon.BITMAP, 155 BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length)); 156 break; 157 case (int) RemoteViewsProto.Icon.ADAPTIVE_BITMAP: 158 final byte[] bitmapAdaptiveData = in.readBytes( 159 RemoteViewsProto.Icon.ADAPTIVE_BITMAP); 160 values.put(RemoteViewsProto.Icon.ADAPTIVE_BITMAP, 161 BitmapFactory.decodeByteArray(bitmapAdaptiveData, 0, 162 bitmapAdaptiveData.length)); 163 break; 164 case (int) RemoteViewsProto.Icon.RESOURCE: 165 values.put( 166 RemoteViewsProto.Icon.RESOURCE, 167 in.readString(RemoteViewsProto.Icon.RESOURCE)); 168 break; 169 case (int) RemoteViewsProto.Icon.DATA: 170 values.put( 171 RemoteViewsProto.Icon.DATA, in.readBytes(RemoteViewsProto.Icon.DATA)); 172 break; 173 case (int) RemoteViewsProto.Icon.URI: 174 values.put(RemoteViewsProto.Icon.URI, in.readString(RemoteViewsProto.Icon.URI)); 175 break; 176 case (int) RemoteViewsProto.Icon.URI_ADAPTIVE_BITMAP: 177 values.put( 178 RemoteViewsProto.Icon.URI_ADAPTIVE_BITMAP, 179 in.readString(RemoteViewsProto.Icon.URI_ADAPTIVE_BITMAP)); 180 break; 181 default: 182 Log.w( 183 TAG, 184 "Unhandled field while reading Icon proto!\n" 185 + ProtoUtils.currentFieldToString(in)); 186 } 187 } 188 189 return (resources) -> { 190 final int blendMode = (int) values.get(RemoteViewsProto.Icon.BLEND_MODE, -1); 191 final ColorStateList tintList = (ColorStateList) values.get( 192 RemoteViewsProto.Icon.TINT_LIST); 193 final Bitmap bitmap = (Bitmap) values.get(RemoteViewsProto.Icon.BITMAP); 194 final Bitmap bitmapAdaptive = (Bitmap) values.get( 195 RemoteViewsProto.Icon.ADAPTIVE_BITMAP); 196 final String resName = (String) values.get(RemoteViewsProto.Icon.RESOURCE); 197 final int resource = resName != null ? resources.getIdentifier(resName, /* defType= */ 198 null, 199 /* defPackage= */ null) : -1; 200 final byte[] data = (byte[]) values.get(RemoteViewsProto.Icon.DATA); 201 final String uri = (String) values.get(RemoteViewsProto.Icon.URI); 202 final String uriAdaptive = (String) values.get( 203 RemoteViewsProto.Icon.URI_ADAPTIVE_BITMAP); 204 Icon icon; 205 if (bitmap != null) { 206 icon = Icon.createWithBitmap(bitmap); 207 } else if (bitmapAdaptive != null) { 208 icon = Icon.createWithAdaptiveBitmap(bitmapAdaptive); 209 } else if (resource != -1) { 210 icon = Icon.createWithResource(resources, resource); 211 } else if (data != null) { 212 icon = Icon.createWithData(data, 0, data.length); 213 } else if (uri != null) { 214 icon = Icon.createWithContentUri(uri); 215 } else if (uriAdaptive != null) { 216 icon = Icon.createWithAdaptiveBitmapContentUri(uriAdaptive); 217 } else { 218 // Either this Icon has no data or is of an unknown type. 219 return null; 220 } 221 222 if (tintList != null) { 223 icon.setTintList(tintList); 224 } 225 if (blendMode != -1) { 226 icon.setTintBlendMode(BlendMode.fromValue(blendMode)); 227 } 228 return icon; 229 }; 230 } 231 writeCharSequenceToProto(@onNull ProtoOutputStream out, @NonNull CharSequence cs)232 public static void writeCharSequenceToProto(@NonNull ProtoOutputStream out, 233 @NonNull CharSequence cs) { 234 out.write(RemoteViewsProto.CharSequence.TEXT, cs.toString()); 235 if (!(cs instanceof Spanned sp)) return; 236 237 Object[] os = sp.getSpans(0, cs.length(), Object.class); 238 for (Object original : os) { 239 Object prop = original; 240 if (prop instanceof CharacterStyle) { 241 prop = ((CharacterStyle) prop).getUnderlying(); 242 } 243 244 final long spansToken = out.start(RemoteViewsProto.CharSequence.SPANS); 245 out.write(RemoteViewsProto.CharSequence.Span.START, sp.getSpanStart(original)); 246 out.write(RemoteViewsProto.CharSequence.Span.END, sp.getSpanEnd(original)); 247 out.write(RemoteViewsProto.CharSequence.Span.FLAGS, sp.getSpanFlags(original)); 248 249 if (prop instanceof AbsoluteSizeSpan span) { 250 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.ABSOLUTE_SIZE); 251 writeAbsoluteSizeSpanToProto(out, span); 252 out.end(spanToken); 253 } else if (prop instanceof AccessibilityClickableSpan span) { 254 final long spanToken = out.start( 255 RemoteViewsProto.CharSequence.Span.ACCESSIBILITY_CLICKABLE); 256 writeAccessibilityClickableSpanToProto(out, span); 257 out.end(spanToken); 258 } else if (prop instanceof AccessibilityReplacementSpan span) { 259 final long spanToken = out.start( 260 RemoteViewsProto.CharSequence.Span.ACCESSIBILITY_REPLACEMENT); 261 writeAccessibilityReplacementSpanToProto(out, span); 262 out.end(spanToken); 263 } else if (prop instanceof AccessibilityURLSpan span) { 264 final long spanToken = out.start( 265 RemoteViewsProto.CharSequence.Span.ACCESSIBILITY_URL); 266 writeAccessibilityURLSpanToProto(out, span); 267 out.end(spanToken); 268 } else if (prop instanceof Annotation span) { 269 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.ANNOTATION); 270 writeAnnotationToProto(out, span); 271 out.end(spanToken); 272 } else if (prop instanceof BackgroundColorSpan span) { 273 final long spanToken = out.start( 274 RemoteViewsProto.CharSequence.Span.BACKGROUND_COLOR); 275 writeBackgroundColorSpanToProto(out, span); 276 out.end(spanToken); 277 } else if (prop instanceof BulletSpan span) { 278 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.BULLET); 279 writeBulletSpanToProto(out, span); 280 out.end(spanToken); 281 } else if (prop instanceof EasyEditSpan span) { 282 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.EASY_EDIT); 283 writeEasyEditSpanToProto(out, span); 284 out.end(spanToken); 285 } else if (prop instanceof ForegroundColorSpan span) { 286 final long spanToken = out.start( 287 RemoteViewsProto.CharSequence.Span.FOREGROUND_COLOR); 288 writeForegroundColorSpanToProto(out, span); 289 out.end(spanToken); 290 } else if (noBreakNoHyphenationSpan() && prop instanceof LineBreakConfigSpan span) { 291 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.LINE_BREAK); 292 writeLineBreakConfigSpanToProto(out, span); 293 out.end(spanToken); 294 } else if (prop instanceof LocaleSpan span) { 295 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.LOCALE); 296 writeLocaleSpanToProto(out, span); 297 out.end(spanToken); 298 } else if (prop instanceof QuoteSpan span) { 299 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.QUOTE); 300 writeQuoteSpanToProto(out, span); 301 out.end(spanToken); 302 } else if (prop instanceof RelativeSizeSpan span) { 303 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.RELATIVE_SIZE); 304 writeRelativeSizeSpanToProto(out, span); 305 out.end(spanToken); 306 } else if (prop instanceof ScaleXSpan span) { 307 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.SCALE_X); 308 writeScaleXSpanToProto(out, span); 309 out.end(spanToken); 310 } else if (prop instanceof SpellCheckSpan span) { 311 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.SPELL_CHECK); 312 writeSpellCheckSpanToProto(out, span); 313 out.end(spanToken); 314 } else if (prop instanceof LineBackgroundSpan.Standard span) { 315 final long spanToken = out.start( 316 RemoteViewsProto.CharSequence.Span.LINE_BACKGROUND); 317 writeLineBackgroundSpanStandardToProto(out, span); 318 out.end(spanToken); 319 } else if (prop instanceof LineHeightSpan.Standard span) { 320 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.LINE_HEIGHT); 321 writeLineHeightSpanStandardToProto(out, span); 322 out.end(spanToken); 323 } else if (prop instanceof LeadingMarginSpan.Standard span) { 324 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.LEADING_MARGIN); 325 writeLeadingMarginSpanStandardToProto(out, span); 326 out.end(spanToken); 327 } else if (prop instanceof AlignmentSpan.Standard span) { 328 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.ALIGNMENT); 329 writeAlignmentSpanStandardToProto(out, span); 330 out.end(spanToken); 331 } else if (prop instanceof StrikethroughSpan span) { 332 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.STRIKETHROUGH); 333 writeStrikethroughSpanToProto(out, span); 334 out.end(spanToken); 335 } else if (prop instanceof StyleSpan span) { 336 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.STYLE); 337 writeStyleSpanToProto(out, span); 338 out.end(spanToken); 339 } else if (prop instanceof SubscriptSpan span) { 340 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.SUBSCRIPT); 341 writeSubscriptSpanToProto(out, span); 342 out.end(spanToken); 343 } else if (prop instanceof SuggestionRangeSpan span) { 344 final long spanToken = out.start( 345 RemoteViewsProto.CharSequence.Span.SUGGESTION_RANGE); 346 writeSuggestionRangeSpanToProto(out, span); 347 out.end(spanToken); 348 } else if (prop instanceof SuggestionSpan span) { 349 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.SUGGESTION); 350 writeSuggestionSpanToProto(out, span); 351 out.end(spanToken); 352 } else if (prop instanceof SuperscriptSpan span) { 353 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.SUPERSCRIPT); 354 writeSuperscriptSpanToProto(out, span); 355 out.end(spanToken); 356 } else if (prop instanceof TextAppearanceSpan span) { 357 final long spanToken = out.start( 358 RemoteViewsProto.CharSequence.Span.TEXT_APPEARANCE); 359 writeTextAppearanceSpanToProto(out, span); 360 out.end(spanToken); 361 } else if (prop instanceof TtsSpan span) { 362 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.TTS); 363 writeTtsSpanToProto(out, span); 364 out.end(spanToken); 365 } else if (prop instanceof TypefaceSpan span) { 366 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.TYPEFACE); 367 writeTypefaceSpanToProto(out, span); 368 out.end(spanToken); 369 } else if (prop instanceof URLSpan span) { 370 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.URL); 371 writeURLSpanToProto(out, span); 372 out.end(spanToken); 373 } else if (prop instanceof UnderlineSpan span) { 374 final long spanToken = out.start(RemoteViewsProto.CharSequence.Span.UNDERLINE); 375 writeUnderlineSpanToProto(out, span); 376 out.end(spanToken); 377 } 378 out.end(spansToken); 379 } 380 } 381 createCharSequenceFromProto(ProtoInputStream in)382 public static CharSequence createCharSequenceFromProto(ProtoInputStream in) throws Exception { 383 SpannableStringBuilder builder = new SpannableStringBuilder(); 384 boolean hasSpans = false; 385 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 386 switch (in.getFieldNumber()) { 387 case (int) RemoteViewsProto.CharSequence.TEXT: 388 String text = in.readString(RemoteViewsProto.CharSequence.TEXT); 389 builder.append(text); 390 break; 391 case (int) RemoteViewsProto.CharSequence.SPANS: 392 hasSpans = true; 393 final long spansToken = in.start(RemoteViewsProto.CharSequence.SPANS); 394 createSpanFromProto(in, builder); 395 in.end(spansToken); 396 break; 397 default: 398 Log.w(TAG, "Unhandled field while reading CharSequence proto!\n" 399 + ProtoUtils.currentFieldToString(in)); 400 } 401 } 402 return hasSpans ? builder : builder.toString(); 403 } 404 createSpanFromProto(ProtoInputStream in, SpannableStringBuilder builder)405 private static void createSpanFromProto(ProtoInputStream in, SpannableStringBuilder builder) 406 throws Exception { 407 int start = 0; 408 int end = 0; 409 int flags = 0; 410 Object what = null; 411 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 412 switch (in.getFieldNumber()) { 413 case (int) RemoteViewsProto.CharSequence.Span.START: 414 start = in.readInt(RemoteViewsProto.CharSequence.Span.START); 415 break; 416 case (int) RemoteViewsProto.CharSequence.Span.END: 417 end = in.readInt(RemoteViewsProto.CharSequence.Span.END); 418 break; 419 case (int) RemoteViewsProto.CharSequence.Span.FLAGS: 420 flags = in.readInt(RemoteViewsProto.CharSequence.Span.FLAGS); 421 break; 422 case (int) RemoteViewsProto.CharSequence.Span.ABSOLUTE_SIZE: 423 final long asToken = in.start(RemoteViewsProto.CharSequence.Span.ABSOLUTE_SIZE); 424 what = createAbsoluteSizeSpanFromProto(in); 425 in.end(asToken); 426 break; 427 case (int) RemoteViewsProto.CharSequence.Span.ACCESSIBILITY_CLICKABLE: 428 final long acToken = in.start( 429 RemoteViewsProto.CharSequence.Span.ACCESSIBILITY_CLICKABLE); 430 what = createAccessibilityClickableSpanFromProto(in); 431 in.end(acToken); 432 break; 433 case (int) RemoteViewsProto.CharSequence.Span.ACCESSIBILITY_REPLACEMENT: 434 final long arToken = in.start( 435 RemoteViewsProto.CharSequence.Span.ACCESSIBILITY_REPLACEMENT); 436 what = createAccessibilityReplacementSpanFromProto(in); 437 in.end(arToken); 438 break; 439 case (int) RemoteViewsProto.CharSequence.Span.ACCESSIBILITY_URL: 440 final long auToken = in.start( 441 RemoteViewsProto.CharSequence.Span.ACCESSIBILITY_URL); 442 what = createAccessibilityURLSpanFromProto(in); 443 in.end(auToken); 444 break; 445 case (int) RemoteViewsProto.CharSequence.Span.ALIGNMENT: 446 final long aToken = in.start(RemoteViewsProto.CharSequence.Span.ALIGNMENT); 447 what = createAlignmentSpanStandardFromProto(in); 448 in.end(aToken); 449 break; 450 case (int) RemoteViewsProto.CharSequence.Span.ANNOTATION: 451 final long annToken = in.start(RemoteViewsProto.CharSequence.Span.ANNOTATION); 452 what = createAnnotationFromProto(in); 453 in.end(annToken); 454 break; 455 case (int) RemoteViewsProto.CharSequence.Span.BACKGROUND_COLOR: 456 final long bcToken = in.start( 457 RemoteViewsProto.CharSequence.Span.BACKGROUND_COLOR); 458 what = createBackgroundColorSpanFromProto(in); 459 in.end(bcToken); 460 break; 461 case (int) RemoteViewsProto.CharSequence.Span.BULLET: 462 final long bToken = in.start(RemoteViewsProto.CharSequence.Span.BULLET); 463 what = createBulletSpanFromProto(in); 464 in.end(bToken); 465 break; 466 case (int) RemoteViewsProto.CharSequence.Span.EASY_EDIT: 467 final long eeToken = in.start(RemoteViewsProto.CharSequence.Span.EASY_EDIT); 468 what = createEasyEditSpanFromProto(in); 469 in.end(eeToken); 470 break; 471 case (int) RemoteViewsProto.CharSequence.Span.FOREGROUND_COLOR: 472 final long fcToken = in.start( 473 RemoteViewsProto.CharSequence.Span.FOREGROUND_COLOR); 474 what = createForegroundColorSpanFromProto(in); 475 in.end(fcToken); 476 break; 477 case (int) RemoteViewsProto.CharSequence.Span.LEADING_MARGIN: 478 final long lmToken = in.start( 479 RemoteViewsProto.CharSequence.Span.LEADING_MARGIN); 480 what = createLeadingMarginSpanStandardFromProto(in); 481 in.end(lmToken); 482 break; 483 case (int) RemoteViewsProto.CharSequence.Span.LINE_BACKGROUND: 484 final long lbToken = in.start( 485 RemoteViewsProto.CharSequence.Span.LINE_BACKGROUND); 486 what = createLineBackgroundSpanStandardFromProto(in); 487 in.end(lbToken); 488 break; 489 case (int) RemoteViewsProto.CharSequence.Span.LINE_BREAK: 490 if (!noBreakNoHyphenationSpan()) { 491 continue; 492 } 493 final long lbrToken = in.start(RemoteViewsProto.CharSequence.Span.LINE_BREAK); 494 what = createLineBreakConfigSpanFromProto(in); 495 in.end(lbrToken); 496 break; 497 case (int) RemoteViewsProto.CharSequence.Span.LINE_HEIGHT: 498 final long lhToken = in.start(RemoteViewsProto.CharSequence.Span.LINE_HEIGHT); 499 what = createLineHeightSpanStandardFromProto(in); 500 in.end(lhToken); 501 break; 502 case (int) RemoteViewsProto.CharSequence.Span.LOCALE: 503 final long lToken = in.start(RemoteViewsProto.CharSequence.Span.LOCALE); 504 what = createLocaleSpanFromProto(in); 505 in.end(lToken); 506 break; 507 case (int) RemoteViewsProto.CharSequence.Span.QUOTE: 508 final long qToken = in.start(RemoteViewsProto.CharSequence.Span.QUOTE); 509 what = createQuoteSpanFromProto(in); 510 in.end(qToken); 511 break; 512 case (int) RemoteViewsProto.CharSequence.Span.RELATIVE_SIZE: 513 final long rsToken = in.start(RemoteViewsProto.CharSequence.Span.RELATIVE_SIZE); 514 what = createRelativeSizeSpanFromProto(in); 515 in.end(rsToken); 516 break; 517 case (int) RemoteViewsProto.CharSequence.Span.SCALE_X: 518 final long sxToken = in.start(RemoteViewsProto.CharSequence.Span.SCALE_X); 519 what = createScaleXSpanFromProto(in); 520 in.end(sxToken); 521 break; 522 case (int) RemoteViewsProto.CharSequence.Span.SPELL_CHECK: 523 final long scToken = in.start(RemoteViewsProto.CharSequence.Span.SPELL_CHECK); 524 what = createSpellCheckSpanFromProto(in); 525 in.end(scToken); 526 break; 527 case (int) RemoteViewsProto.CharSequence.Span.STRIKETHROUGH: 528 final long stToken = in.start(RemoteViewsProto.CharSequence.Span.STRIKETHROUGH); 529 what = createStrikethroughSpanFromProto(in); 530 in.end(stToken); 531 break; 532 case (int) RemoteViewsProto.CharSequence.Span.STYLE: 533 final long sToken = in.start(RemoteViewsProto.CharSequence.Span.STYLE); 534 what = createStyleSpanFromProto(in); 535 in.end(sToken); 536 break; 537 case (int) RemoteViewsProto.CharSequence.Span.SUBSCRIPT: 538 final long suToken = in.start(RemoteViewsProto.CharSequence.Span.SUBSCRIPT); 539 what = createSubscriptSpanFromProto(in); 540 in.end(suToken); 541 break; 542 case (int) RemoteViewsProto.CharSequence.Span.SUGGESTION_RANGE: 543 final long srToken = in.start( 544 RemoteViewsProto.CharSequence.Span.SUGGESTION_RANGE); 545 what = createSuggestionRangeSpanFromProto(in); 546 in.end(srToken); 547 break; 548 case (int) RemoteViewsProto.CharSequence.Span.SUGGESTION: 549 final long sugToken = in.start(RemoteViewsProto.CharSequence.Span.SUGGESTION); 550 what = createSuggestionSpanFromProto(in); 551 in.end(sugToken); 552 break; 553 case (int) RemoteViewsProto.CharSequence.Span.SUPERSCRIPT: 554 final long supToken = in.start(RemoteViewsProto.CharSequence.Span.SUPERSCRIPT); 555 what = createSuperscriptSpanFromProto(in); 556 in.end(supToken); 557 break; 558 case (int) RemoteViewsProto.CharSequence.Span.TEXT_APPEARANCE: 559 final long taToken = in.start( 560 RemoteViewsProto.CharSequence.Span.TEXT_APPEARANCE); 561 what = createTextAppearanceSpanFromProto(in); 562 in.end(taToken); 563 break; 564 case (int) RemoteViewsProto.CharSequence.Span.TTS: 565 final long ttsToken = in.start(RemoteViewsProto.CharSequence.Span.TTS); 566 what = createTtsSpanFromProto(in); 567 in.end(ttsToken); 568 break; 569 case (int) RemoteViewsProto.CharSequence.Span.TYPEFACE: 570 final long tfToken = in.start(RemoteViewsProto.CharSequence.Span.TYPEFACE); 571 what = createTypefaceSpanFromProto(in); 572 in.end(tfToken); 573 break; 574 case (int) RemoteViewsProto.CharSequence.Span.UNDERLINE: 575 final long unToken = in.start(RemoteViewsProto.CharSequence.Span.UNDERLINE); 576 what = createUnderlineSpanFromProto(in); 577 in.end(unToken); 578 break; 579 case (int) RemoteViewsProto.CharSequence.Span.URL: 580 final long urlToken = in.start(RemoteViewsProto.CharSequence.Span.URL); 581 what = createURLSpanFromProto(in); 582 in.end(urlToken); 583 break; 584 default: 585 Log.w(TAG, "Unhandled field while reading CharSequence proto!\n" 586 + ProtoUtils.currentFieldToString(in)); 587 } 588 } 589 if (what == null) { 590 return; 591 } 592 builder.setSpan(what, start, end, flags); 593 } 594 createAbsoluteSizeSpanFromProto(@onNull ProtoInputStream in)595 public static AbsoluteSizeSpan createAbsoluteSizeSpanFromProto(@NonNull ProtoInputStream in) 596 throws Exception { 597 int size = 0; 598 boolean dip = false; 599 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 600 switch (in.getFieldNumber()) { 601 case (int) RemoteViewsProto.CharSequence.Span.AbsoluteSize.SIZE: 602 size = in.readInt(RemoteViewsProto.CharSequence.Span.AbsoluteSize.SIZE); 603 break; 604 case (int) RemoteViewsProto.CharSequence.Span.AbsoluteSize.DIP: 605 dip = in.readBoolean(RemoteViewsProto.CharSequence.Span.AbsoluteSize.DIP); 606 break; 607 default: 608 Log.w("AbsoluteSizeSpan", 609 "Unhandled field while reading AbsoluteSizeSpan " + "proto!\n" 610 + ProtoUtils.currentFieldToString(in)); 611 } 612 } 613 return new AbsoluteSizeSpan(size, dip); 614 } 615 writeAbsoluteSizeSpanToProto(@onNull ProtoOutputStream out, AbsoluteSizeSpan span)616 public static void writeAbsoluteSizeSpanToProto(@NonNull ProtoOutputStream out, 617 AbsoluteSizeSpan span) { 618 out.write(RemoteViewsProto.CharSequence.Span.AbsoluteSize.SIZE, span.getSize()); 619 out.write(RemoteViewsProto.CharSequence.Span.AbsoluteSize.DIP, span.getDip()); 620 } 621 createAccessibilityClickableSpanFromProto( @onNull ProtoInputStream in)622 public static AccessibilityClickableSpan createAccessibilityClickableSpanFromProto( 623 @NonNull ProtoInputStream in) throws Exception { 624 int originalClickableSpanId = 0; 625 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 626 switch (in.getFieldNumber()) { 627 case (int) RemoteViewsProto.CharSequence.Span 628 .AccessibilityClickable.ORIGINAL_CLICKABLE_SPAN_ID: 629 originalClickableSpanId = in.readInt( 630 RemoteViewsProto.CharSequence.Span 631 .AccessibilityClickable.ORIGINAL_CLICKABLE_SPAN_ID); 632 break; 633 default: 634 Log.w("AccessibilityClickable", 635 "Unhandled field while reading" + " AccessibilityClickableSpan proto!\n" 636 + ProtoUtils.currentFieldToString(in)); 637 } 638 } 639 return new AccessibilityClickableSpan(originalClickableSpanId); 640 } 641 writeAccessibilityClickableSpanToProto(@onNull ProtoOutputStream out, AccessibilityClickableSpan span)642 public static void writeAccessibilityClickableSpanToProto(@NonNull ProtoOutputStream out, 643 AccessibilityClickableSpan span) { 644 out.write( 645 RemoteViewsProto.CharSequence.Span 646 .AccessibilityClickable.ORIGINAL_CLICKABLE_SPAN_ID, 647 span.getOriginalClickableSpanId()); 648 } 649 createAccessibilityReplacementSpanFromProto( @onNull ProtoInputStream in)650 public static AccessibilityReplacementSpan createAccessibilityReplacementSpanFromProto( 651 @NonNull ProtoInputStream in) throws Exception { 652 CharSequence contentDescription = null; 653 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 654 switch (in.getFieldNumber()) { 655 case (int) RemoteViewsProto.CharSequence.Span 656 .AccessibilityReplacement.CONTENT_DESCRIPTION: 657 final long token = in.start( 658 RemoteViewsProto.CharSequence.Span 659 .AccessibilityReplacement.CONTENT_DESCRIPTION); 660 contentDescription = createCharSequenceFromProto(in); 661 in.end(token); 662 break; 663 default: 664 Log.w("AccessibilityReplacemen", "Unhandled field while reading" 665 + " AccessibilityReplacementSpan proto!\n" 666 + ProtoUtils.currentFieldToString(in)); 667 } 668 } 669 return new AccessibilityReplacementSpan(contentDescription); 670 } 671 writeAccessibilityReplacementSpanToProto(@onNull ProtoOutputStream out, AccessibilityReplacementSpan span)672 public static void writeAccessibilityReplacementSpanToProto(@NonNull ProtoOutputStream out, 673 AccessibilityReplacementSpan span) { 674 final long token = out.start( 675 RemoteViewsProto.CharSequence.Span.AccessibilityReplacement.CONTENT_DESCRIPTION); 676 CharSequence description = span.getContentDescription(); 677 if (description != null) { 678 writeCharSequenceToProto(out, description); 679 } 680 out.end(token); 681 } 682 createAccessibilityURLSpanFromProto(ProtoInputStream in)683 public static AccessibilityURLSpan createAccessibilityURLSpanFromProto(ProtoInputStream in) 684 throws Exception { 685 String url = null; 686 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 687 switch (in.getFieldNumber()) { 688 case (int) RemoteViewsProto.CharSequence.Span.AccessibilityUrl.URL: 689 url = in.readString(RemoteViewsProto.CharSequence.Span.AccessibilityUrl.URL); 690 break; 691 default: 692 Log.w("AccessibilityURLSpan", 693 "Unhandled field while reading AccessibilityURLSpan " + "proto!\n" 694 + ProtoUtils.currentFieldToString(in)); 695 } 696 } 697 return new AccessibilityURLSpan(new URLSpan(url)); 698 } 699 writeAccessibilityURLSpanToProto(@onNull ProtoOutputStream out, AccessibilityURLSpan span)700 public static void writeAccessibilityURLSpanToProto(@NonNull ProtoOutputStream out, 701 AccessibilityURLSpan span) { 702 out.write(RemoteViewsProto.CharSequence.Span.AccessibilityUrl.URL, span.getURL()); 703 } 704 createAlignmentSpanStandardFromProto( @onNull ProtoInputStream in)705 public static AlignmentSpan.Standard createAlignmentSpanStandardFromProto( 706 @NonNull ProtoInputStream in) throws Exception { 707 String alignment = null; 708 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 709 switch (in.getFieldNumber()) { 710 case (int) RemoteViewsProto.CharSequence.Span.Alignment.ALIGNMENT: 711 alignment = in.readString( 712 RemoteViewsProto.CharSequence.Span.Alignment.ALIGNMENT); 713 break; 714 default: 715 Log.w("AlignmentSpan", 716 "Unhandled field while reading AlignmentSpan " + "proto!\n" 717 + ProtoUtils.currentFieldToString(in)); 718 } 719 } 720 return new AlignmentSpan.Standard(Layout.Alignment.valueOf(alignment)); 721 } 722 writeAlignmentSpanStandardToProto(@onNull ProtoOutputStream out, AlignmentSpan.Standard span)723 public static void writeAlignmentSpanStandardToProto(@NonNull ProtoOutputStream out, 724 AlignmentSpan.Standard span) { 725 out.write(RemoteViewsProto.CharSequence.Span.Alignment.ALIGNMENT, 726 span.getAlignment().name()); 727 } 728 createAnnotationFromProto(@onNull ProtoInputStream in)729 public static Annotation createAnnotationFromProto(@NonNull ProtoInputStream in) 730 throws Exception { 731 String key = null; 732 String value = null; 733 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 734 switch (in.getFieldNumber()) { 735 case (int) RemoteViewsProto.CharSequence.Span.Annotation.KEY: 736 key = in.readString(RemoteViewsProto.CharSequence.Span.Annotation.KEY); 737 break; 738 case (int) RemoteViewsProto.CharSequence.Span.Annotation.VALUE: 739 value = in.readString(RemoteViewsProto.CharSequence.Span.Annotation.VALUE); 740 break; 741 default: 742 Log.w("Annotation", "Unhandled field while reading" + " Annotation proto!\n" 743 + ProtoUtils.currentFieldToString(in)); 744 } 745 } 746 return new Annotation(key, value); 747 } 748 writeAnnotationToProto(@onNull ProtoOutputStream out, Annotation span)749 public static void writeAnnotationToProto(@NonNull ProtoOutputStream out, Annotation span) { 750 out.write(RemoteViewsProto.CharSequence.Span.Annotation.KEY, span.getKey()); 751 out.write(RemoteViewsProto.CharSequence.Span.Annotation.VALUE, span.getValue()); 752 } 753 createBackgroundColorSpanFromProto( @onNull ProtoInputStream in)754 public static BackgroundColorSpan createBackgroundColorSpanFromProto( 755 @NonNull ProtoInputStream in) throws Exception { 756 int color = 0; 757 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 758 switch (in.getFieldNumber()) { 759 case (int) RemoteViewsProto.CharSequence.Span.BackgroundColor.COLOR: 760 color = in.readInt(RemoteViewsProto.CharSequence.Span.BackgroundColor.COLOR); 761 break; 762 default: 763 Log.w("BackgroundColorSpan", 764 "Unhandled field while reading" + " BackgroundColorSpan proto!\n" 765 + ProtoUtils.currentFieldToString(in)); 766 } 767 } 768 return new BackgroundColorSpan(color); 769 } 770 writeBackgroundColorSpanToProto(@onNull ProtoOutputStream out, BackgroundColorSpan span)771 public static void writeBackgroundColorSpanToProto(@NonNull ProtoOutputStream out, 772 BackgroundColorSpan span) { 773 out.write(RemoteViewsProto.CharSequence.Span.BackgroundColor.COLOR, 774 span.getBackgroundColor()); 775 } 776 createBulletSpanFromProto(@onNull ProtoInputStream in)777 public static BulletSpan createBulletSpanFromProto(@NonNull ProtoInputStream in) 778 throws Exception { 779 int bulletRadius = 0; 780 int color = 0; 781 int gapWidth = 0; 782 boolean wantColor = false; 783 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 784 switch (in.getFieldNumber()) { 785 case (int) RemoteViewsProto.CharSequence.Span.Bullet.BULLET_RADIUS: 786 bulletRadius = in.readInt( 787 RemoteViewsProto.CharSequence.Span.Bullet.BULLET_RADIUS); 788 break; 789 case (int) RemoteViewsProto.CharSequence.Span.Bullet.COLOR: 790 color = in.readInt(RemoteViewsProto.CharSequence.Span.Bullet.COLOR); 791 break; 792 case (int) RemoteViewsProto.CharSequence.Span.Bullet.GAP_WIDTH: 793 gapWidth = in.readInt(RemoteViewsProto.CharSequence.Span.Bullet.GAP_WIDTH); 794 break; 795 case (int) RemoteViewsProto.CharSequence.Span.Bullet.WANT_COLOR: 796 wantColor = in.readBoolean( 797 RemoteViewsProto.CharSequence.Span.Bullet.WANT_COLOR); 798 break; 799 default: 800 Log.w("BulletSpan", "Unhandled field while reading BulletSpan " + "proto!\n" 801 + ProtoUtils.currentFieldToString(in)); 802 } 803 } 804 return new BulletSpan(gapWidth, color, wantColor, bulletRadius); 805 } 806 writeBulletSpanToProto(@onNull ProtoOutputStream out, BulletSpan span)807 public static void writeBulletSpanToProto(@NonNull ProtoOutputStream out, BulletSpan span) { 808 out.write(RemoteViewsProto.CharSequence.Span.Bullet.BULLET_RADIUS, span.getBulletRadius()); 809 out.write(RemoteViewsProto.CharSequence.Span.Bullet.COLOR, span.getColor()); 810 out.write(RemoteViewsProto.CharSequence.Span.Bullet.GAP_WIDTH, span.getGapWidth()); 811 out.write(RemoteViewsProto.CharSequence.Span.Bullet.WANT_COLOR, span.getWantColor()); 812 } 813 createEasyEditSpanFromProto(@onNull ProtoInputStream in)814 public static EasyEditSpan createEasyEditSpanFromProto(@NonNull ProtoInputStream in) 815 throws Exception { 816 return new EasyEditSpan(); 817 } 818 writeEasyEditSpanToProto(@onNull ProtoOutputStream out, EasyEditSpan span)819 public static void writeEasyEditSpanToProto(@NonNull ProtoOutputStream out, EasyEditSpan span) { 820 } 821 createForegroundColorSpanFromProto( @onNull ProtoInputStream in)822 public static ForegroundColorSpan createForegroundColorSpanFromProto( 823 @NonNull ProtoInputStream in) throws Exception { 824 int color = 0; 825 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 826 switch (in.getFieldNumber()) { 827 case (int) RemoteViewsProto.CharSequence.Span.BackgroundColor.COLOR: 828 color = in.readInt(RemoteViewsProto.CharSequence.Span.BackgroundColor.COLOR); 829 break; 830 default: 831 Log.w("ForegroundColorSpan", 832 "Unhandled field while reading" + " ForegroundColorSpan proto!\n" 833 + ProtoUtils.currentFieldToString(in)); 834 } 835 } 836 return new ForegroundColorSpan(color); 837 } 838 createLeadingMarginSpanStandardFromProto( @onNull ProtoInputStream in)839 public static LeadingMarginSpan.Standard createLeadingMarginSpanStandardFromProto( 840 @NonNull ProtoInputStream in) throws Exception { 841 int first = 0; 842 int rest = 0; 843 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 844 switch (in.getFieldNumber()) { 845 case (int) RemoteViewsProto.CharSequence.Span.LeadingMargin.FIRST: 846 first = in.readInt(RemoteViewsProto.CharSequence.Span.LeadingMargin.FIRST); 847 break; 848 case (int) RemoteViewsProto.CharSequence.Span.LeadingMargin.REST: 849 rest = in.readInt(RemoteViewsProto.CharSequence.Span.LeadingMargin.REST); 850 break; 851 default: 852 Log.w("LeadingMarginSpan", 853 "Unhandled field while reading LeadingMarginSpan" + "proto!\n" 854 + ProtoUtils.currentFieldToString(in)); 855 } 856 } 857 return new LeadingMarginSpan.Standard(first, rest); 858 } 859 writeLeadingMarginSpanStandardToProto(@onNull ProtoOutputStream out, LeadingMarginSpan.Standard span)860 public static void writeLeadingMarginSpanStandardToProto(@NonNull ProtoOutputStream out, 861 LeadingMarginSpan.Standard span) { 862 out.write(RemoteViewsProto.CharSequence.Span.LeadingMargin.FIRST, 863 span.getLeadingMargin(/* first= */ true)); 864 out.write(RemoteViewsProto.CharSequence.Span.LeadingMargin.REST, 865 span.getLeadingMargin(/* first= */ false)); 866 } 867 writeForegroundColorSpanToProto(@onNull ProtoOutputStream out, ForegroundColorSpan span)868 public static void writeForegroundColorSpanToProto(@NonNull ProtoOutputStream out, 869 ForegroundColorSpan span) { 870 out.write(RemoteViewsProto.CharSequence.Span.ForegroundColor.COLOR, 871 span.getForegroundColor()); 872 } 873 createLineBackgroundSpanStandardFromProto( @onNull ProtoInputStream in)874 public static LineBackgroundSpan.Standard createLineBackgroundSpanStandardFromProto( 875 @NonNull ProtoInputStream in) throws Exception { 876 int color = 0; 877 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 878 switch (in.getFieldNumber()) { 879 case (int) RemoteViewsProto.CharSequence.Span.LineBackground.COLOR: 880 color = in.readInt(RemoteViewsProto.CharSequence.Span.LineBackground.COLOR); 881 break; 882 default: 883 Log.w("LineBackgroundSpan", 884 "Unhandled field while reading" + " LineBackgroundSpan proto!\n" 885 + ProtoUtils.currentFieldToString(in)); 886 } 887 } 888 return new LineBackgroundSpan.Standard(color); 889 } 890 writeLineBackgroundSpanStandardToProto(@onNull ProtoOutputStream out, LineBackgroundSpan.Standard span)891 public static void writeLineBackgroundSpanStandardToProto(@NonNull ProtoOutputStream out, 892 LineBackgroundSpan.Standard span) { 893 out.write(RemoteViewsProto.CharSequence.Span.LineBackground.COLOR, span.getColor()); 894 } 895 896 @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN) createLineBreakConfigSpanFromProto( @onNull ProtoInputStream in)897 public static LineBreakConfigSpan createLineBreakConfigSpanFromProto( 898 @NonNull ProtoInputStream in) throws Exception { 899 int lineBreakStyle = 0; 900 int lineBreakWordStyle = 0; 901 int hyphenation = 0; 902 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 903 switch (in.getFieldNumber()) { 904 case (int) RemoteViewsProto.CharSequence.Span.LineBreak.LINE_BREAK_STYLE: 905 lineBreakStyle = in.readInt( 906 RemoteViewsProto.CharSequence.Span.LineBreak.LINE_BREAK_STYLE); 907 break; 908 case (int) RemoteViewsProto.CharSequence.Span.LineBreak.LINE_BREAK_WORD_STYLE: 909 lineBreakWordStyle = in.readInt( 910 RemoteViewsProto.CharSequence.Span.LineBreak.LINE_BREAK_WORD_STYLE); 911 break; 912 case (int) RemoteViewsProto.CharSequence.Span.LineBreak.HYPHENATION: 913 hyphenation = in.readInt( 914 RemoteViewsProto.CharSequence.Span.LineBreak.HYPHENATION); 915 break; 916 default: 917 Log.w("LineBreakConfigSpan", 918 "Unhandled field while reading " + "LineBreakConfigSpan proto!\n" 919 + ProtoUtils.currentFieldToString(in)); 920 } 921 } 922 LineBreakConfig lbc = new LineBreakConfig.Builder().setLineBreakStyle( 923 lineBreakStyle).setLineBreakWordStyle(lineBreakWordStyle).setHyphenation( 924 hyphenation).build(); 925 return new LineBreakConfigSpan(lbc); 926 } 927 928 @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN) writeLineBreakConfigSpanToProto(@onNull ProtoOutputStream out, LineBreakConfigSpan span)929 public static void writeLineBreakConfigSpanToProto(@NonNull ProtoOutputStream out, 930 LineBreakConfigSpan span) { 931 out.write(RemoteViewsProto.CharSequence.Span.LineBreak.LINE_BREAK_STYLE, 932 span.getLineBreakConfig().getLineBreakStyle()); 933 out.write(RemoteViewsProto.CharSequence.Span.LineBreak.LINE_BREAK_WORD_STYLE, 934 span.getLineBreakConfig().getLineBreakWordStyle()); 935 out.write(RemoteViewsProto.CharSequence.Span.LineBreak.HYPHENATION, 936 span.getLineBreakConfig().getHyphenation()); 937 } 938 createLineHeightSpanStandardFromProto( @onNull ProtoInputStream in)939 public static LineHeightSpan.Standard createLineHeightSpanStandardFromProto( 940 @NonNull ProtoInputStream in) throws Exception { 941 int height = 0; 942 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 943 switch (in.getFieldNumber()) { 944 case (int) RemoteViewsProto.CharSequence.Span.LineHeight.HEIGHT: 945 height = in.readInt(RemoteViewsProto.CharSequence.Span.LineHeight.HEIGHT); 946 break; 947 default: 948 Log.w("LineHeightSpan.Standard", 949 "Unhandled field while reading" + " LineHeightSpan.Standard proto!\n" 950 + ProtoUtils.currentFieldToString(in)); 951 } 952 } 953 return new LineHeightSpan.Standard(height); 954 } 955 writeLineHeightSpanStandardToProto(@onNull ProtoOutputStream out, LineHeightSpan.Standard span)956 public static void writeLineHeightSpanStandardToProto(@NonNull ProtoOutputStream out, 957 LineHeightSpan.Standard span) { 958 out.write(RemoteViewsProto.CharSequence.Span.LineHeight.HEIGHT, span.getHeight()); 959 } 960 createLocaleSpanFromProto(@onNull ProtoInputStream in)961 public static LocaleSpan createLocaleSpanFromProto(@NonNull ProtoInputStream in) 962 throws Exception { 963 String languageTags = null; 964 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 965 switch (in.getFieldNumber()) { 966 case (int) RemoteViewsProto.CharSequence.Span.Locale.LANGUAGE_TAGS: 967 languageTags = in.readString( 968 RemoteViewsProto.CharSequence.Span.Locale.LANGUAGE_TAGS); 969 break; 970 default: 971 Log.w("LocaleSpan", "Unhandled field while reading" + " LocaleSpan proto!\n" 972 + ProtoUtils.currentFieldToString(in)); 973 } 974 } 975 return new LocaleSpan(LocaleList.forLanguageTags(languageTags)); 976 } 977 writeLocaleSpanToProto(@onNull ProtoOutputStream out, LocaleSpan span)978 public static void writeLocaleSpanToProto(@NonNull ProtoOutputStream out, LocaleSpan span) { 979 out.write(RemoteViewsProto.CharSequence.Span.Locale.LANGUAGE_TAGS, 980 span.getLocales().toLanguageTags()); 981 } 982 createQuoteSpanFromProto(@onNull ProtoInputStream in)983 public static QuoteSpan createQuoteSpanFromProto(@NonNull ProtoInputStream in) 984 throws Exception { 985 int color = 0; 986 int stripeWidth = 0; 987 int gapWidth = 0; 988 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 989 switch (in.getFieldNumber()) { 990 case (int) RemoteViewsProto.CharSequence.Span.Quote.COLOR: 991 color = in.readInt(RemoteViewsProto.CharSequence.Span.Quote.COLOR); 992 break; 993 case (int) RemoteViewsProto.CharSequence.Span.Quote.STRIPE_WIDTH: 994 stripeWidth = in.readInt(RemoteViewsProto.CharSequence.Span.Quote.STRIPE_WIDTH); 995 break; 996 case (int) RemoteViewsProto.CharSequence.Span.Quote.GAP_WIDTH: 997 gapWidth = in.readInt(RemoteViewsProto.CharSequence.Span.Quote.GAP_WIDTH); 998 break; 999 default: 1000 Log.w("QuoteSpan", "Unhandled field while reading QuoteSpan " + "proto!\n" 1001 + ProtoUtils.currentFieldToString(in)); 1002 } 1003 } 1004 return new QuoteSpan(color, stripeWidth, gapWidth); 1005 } 1006 writeQuoteSpanToProto(@onNull ProtoOutputStream out, QuoteSpan span)1007 public static void writeQuoteSpanToProto(@NonNull ProtoOutputStream out, QuoteSpan span) { 1008 out.write(RemoteViewsProto.CharSequence.Span.Quote.COLOR, span.getColor()); 1009 out.write(RemoteViewsProto.CharSequence.Span.Quote.STRIPE_WIDTH, span.getStripeWidth()); 1010 out.write(RemoteViewsProto.CharSequence.Span.Quote.GAP_WIDTH, span.getGapWidth()); 1011 } 1012 createRelativeSizeSpanFromProto(@onNull ProtoInputStream in)1013 public static RelativeSizeSpan createRelativeSizeSpanFromProto(@NonNull ProtoInputStream in) 1014 throws Exception { 1015 float proportion = 0; 1016 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1017 switch (in.getFieldNumber()) { 1018 case (int) RemoteViewsProto.CharSequence.Span.RelativeSize.PROPORTION: 1019 proportion = in.readFloat( 1020 RemoteViewsProto.CharSequence.Span.RelativeSize.PROPORTION); 1021 break; 1022 default: 1023 Log.w("RelativeSizeSpan", 1024 "Unhandled field while reading" + " RelativeSizeSpan proto!\n" 1025 + ProtoUtils.currentFieldToString(in)); 1026 } 1027 } 1028 return new RelativeSizeSpan(proportion); 1029 } 1030 writeRelativeSizeSpanToProto(@onNull ProtoOutputStream out, RelativeSizeSpan span)1031 public static void writeRelativeSizeSpanToProto(@NonNull ProtoOutputStream out, 1032 RelativeSizeSpan span) { 1033 out.write(RemoteViewsProto.CharSequence.Span.RelativeSize.PROPORTION, span.getSizeChange()); 1034 } 1035 createScaleXSpanFromProto(@onNull ProtoInputStream in)1036 public static ScaleXSpan createScaleXSpanFromProto(@NonNull ProtoInputStream in) 1037 throws Exception { 1038 float proportion = 0f; 1039 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1040 switch (in.getFieldNumber()) { 1041 case (int) RemoteViewsProto.CharSequence.Span.ScaleX.PROPORTION: 1042 proportion = in.readFloat(RemoteViewsProto.CharSequence.Span.ScaleX.PROPORTION); 1043 break; 1044 default: 1045 Log.w("ScaleXSpan", "Unhandled field while reading" + " ScaleXSpan proto!\n" 1046 + ProtoUtils.currentFieldToString(in)); 1047 } 1048 } 1049 return new ScaleXSpan(proportion); 1050 } 1051 writeScaleXSpanToProto(@onNull ProtoOutputStream out, ScaleXSpan span)1052 public static void writeScaleXSpanToProto(@NonNull ProtoOutputStream out, ScaleXSpan span) { 1053 out.write(RemoteViewsProto.CharSequence.Span.ScaleX.PROPORTION, span.getScaleX()); 1054 } 1055 createSpellCheckSpanFromProto(@onNull ProtoInputStream in)1056 public static SpellCheckSpan createSpellCheckSpanFromProto(@NonNull ProtoInputStream in) { 1057 return new SpellCheckSpan(); 1058 } 1059 writeSpellCheckSpanToProto(@onNull ProtoOutputStream out, SpellCheckSpan span)1060 public static void writeSpellCheckSpanToProto(@NonNull ProtoOutputStream out, 1061 SpellCheckSpan span) { 1062 } 1063 createStrikethroughSpanFromProto(@onNull ProtoInputStream in)1064 public static StrikethroughSpan createStrikethroughSpanFromProto(@NonNull ProtoInputStream in) { 1065 return new StrikethroughSpan(); 1066 } 1067 writeStrikethroughSpanToProto(@onNull ProtoOutputStream out, StrikethroughSpan span)1068 public static void writeStrikethroughSpanToProto(@NonNull ProtoOutputStream out, 1069 StrikethroughSpan span) { 1070 } 1071 createStyleSpanFromProto(@onNull ProtoInputStream in)1072 public static StyleSpan createStyleSpanFromProto(@NonNull ProtoInputStream in) 1073 throws Exception { 1074 int style = 0; 1075 int fontWeightAdjustment = 0; 1076 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1077 switch (in.getFieldNumber()) { 1078 case (int) RemoteViewsProto.CharSequence.Span.Style.STYLE: 1079 style = in.readInt(RemoteViewsProto.CharSequence.Span.Style.STYLE); 1080 break; 1081 case (int) RemoteViewsProto.CharSequence.Span.Style.FONT_WEIGHT_ADJUSTMENT: 1082 fontWeightAdjustment = in.readInt( 1083 RemoteViewsProto.CharSequence.Span.Style.FONT_WEIGHT_ADJUSTMENT); 1084 break; 1085 default: 1086 Log.w("StyleSpan", "Unhandled field while reading StyleSpan " + "proto!\n" 1087 + ProtoUtils.currentFieldToString(in)); 1088 } 1089 } 1090 return new StyleSpan(style, fontWeightAdjustment); 1091 } 1092 writeStyleSpanToProto(@onNull ProtoOutputStream out, StyleSpan span)1093 public static void writeStyleSpanToProto(@NonNull ProtoOutputStream out, StyleSpan span) { 1094 out.write(RemoteViewsProto.CharSequence.Span.Style.STYLE, span.getStyle()); 1095 out.write(RemoteViewsProto.CharSequence.Span.Style.FONT_WEIGHT_ADJUSTMENT, 1096 span.getFontWeightAdjustment()); 1097 } 1098 createSubscriptSpanFromProto(@onNull ProtoInputStream in)1099 public static SubscriptSpan createSubscriptSpanFromProto(@NonNull ProtoInputStream in) { 1100 return new SubscriptSpan(); 1101 } 1102 writeSubscriptSpanToProto(@onNull ProtoOutputStream out, SubscriptSpan span)1103 public static void writeSubscriptSpanToProto(@NonNull ProtoOutputStream out, 1104 SubscriptSpan span) { 1105 } 1106 createSuggestionRangeSpanFromProto( @onNull ProtoInputStream in)1107 public static SuggestionRangeSpan createSuggestionRangeSpanFromProto( 1108 @NonNull ProtoInputStream in) throws Exception { 1109 int backgroundColor = 0; 1110 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1111 switch (in.getFieldNumber()) { 1112 case (int) RemoteViewsProto.CharSequence.Span.SuggestionRange.BACKGROUND_COLOR: 1113 backgroundColor = in.readInt( 1114 RemoteViewsProto.CharSequence.Span.SuggestionRange.BACKGROUND_COLOR); 1115 break; 1116 default: 1117 Log.w("SuggestionRangeSpan", 1118 "Unhandled field while reading" + " SuggestionRangeSpan proto!\n" 1119 + ProtoUtils.currentFieldToString(in)); 1120 } 1121 } 1122 SuggestionRangeSpan span = new SuggestionRangeSpan(); 1123 span.setBackgroundColor(backgroundColor); 1124 return span; 1125 } 1126 writeSuggestionRangeSpanToProto(@onNull ProtoOutputStream out, SuggestionRangeSpan span)1127 public static void writeSuggestionRangeSpanToProto(@NonNull ProtoOutputStream out, 1128 SuggestionRangeSpan span) { 1129 out.write(RemoteViewsProto.CharSequence.Span.SuggestionRange.BACKGROUND_COLOR, 1130 span.getBackgroundColor()); 1131 } 1132 createSuggestionSpanFromProto(@onNull ProtoInputStream in)1133 public static SuggestionSpan createSuggestionSpanFromProto(@NonNull ProtoInputStream in) 1134 throws Exception { 1135 List<String> suggestions = new ArrayList<>(); 1136 int flags = 0; 1137 String localeStringForCompatibility = null; 1138 String languageTag = null; 1139 int hashCode = 0; 1140 int easyCorrectUnderlineColor = 0; 1141 float easyCorrectUnderlineThickness = 0; 1142 int misspelledUnderlineColor = 0; 1143 float misspelledUnderlineThickness = 0; 1144 int autoCorrectionUnderlineColor = 0; 1145 float autoCorrectionUnderlineThickness = 0; 1146 int grammarErrorUnderlineColor = 0; 1147 float grammarErrorUnderlineThickness = 0; 1148 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1149 switch (in.getFieldNumber()) { 1150 case (int) RemoteViewsProto.CharSequence.Span.Suggestion.SUGGESTIONS: 1151 suggestions.add(in.readString( 1152 RemoteViewsProto.CharSequence.Span.Suggestion.SUGGESTIONS)); 1153 break; 1154 case (int) RemoteViewsProto.CharSequence.Span.Suggestion.FLAGS: 1155 flags = in.readInt(RemoteViewsProto.CharSequence.Span.Suggestion.FLAGS); 1156 break; 1157 case (int) RemoteViewsProto.CharSequence.Span 1158 .Suggestion.LOCALE_STRING_FOR_COMPATIBILITY: 1159 localeStringForCompatibility = in.readString( 1160 RemoteViewsProto.CharSequence.Span 1161 .Suggestion.LOCALE_STRING_FOR_COMPATIBILITY); 1162 break; 1163 case (int) RemoteViewsProto.CharSequence.Span.Suggestion.LANGUAGE_TAG: 1164 languageTag = in.readString( 1165 RemoteViewsProto.CharSequence.Span.Suggestion.LANGUAGE_TAG); 1166 break; 1167 case (int) RemoteViewsProto.CharSequence.Span.Suggestion.HASH_CODE: 1168 hashCode = in.readInt(RemoteViewsProto.CharSequence.Span.Suggestion.HASH_CODE); 1169 break; 1170 case (int) RemoteViewsProto.CharSequence.Span 1171 .Suggestion.EASY_CORRECT_UNDERLINE_COLOR: 1172 easyCorrectUnderlineColor = in.readInt( 1173 RemoteViewsProto.CharSequence.Span 1174 .Suggestion.EASY_CORRECT_UNDERLINE_COLOR); 1175 break; 1176 case (int) RemoteViewsProto.CharSequence.Span 1177 .Suggestion.EASY_CORRECT_UNDERLINE_THICKNESS: 1178 easyCorrectUnderlineThickness = in.readFloat( 1179 RemoteViewsProto.CharSequence.Span 1180 .Suggestion.EASY_CORRECT_UNDERLINE_THICKNESS); 1181 break; 1182 case (int) RemoteViewsProto.CharSequence.Span 1183 .Suggestion.MISSPELLED_UNDERLINE_COLOR: 1184 misspelledUnderlineColor = in.readInt( 1185 RemoteViewsProto.CharSequence.Span 1186 .Suggestion.MISSPELLED_UNDERLINE_COLOR); 1187 break; 1188 case (int) RemoteViewsProto.CharSequence.Span 1189 .Suggestion.MISSPELLED_UNDERLINE_THICKNESS: 1190 misspelledUnderlineThickness = in.readFloat( 1191 RemoteViewsProto.CharSequence.Span 1192 .Suggestion.MISSPELLED_UNDERLINE_THICKNESS); 1193 break; 1194 case (int) RemoteViewsProto.CharSequence.Span 1195 .Suggestion.AUTO_CORRECTION_UNDERLINE_COLOR: 1196 autoCorrectionUnderlineColor = in.readInt( 1197 RemoteViewsProto.CharSequence.Span 1198 .Suggestion.AUTO_CORRECTION_UNDERLINE_COLOR); 1199 break; 1200 case (int) RemoteViewsProto.CharSequence.Span 1201 .Suggestion.AUTO_CORRECTION_UNDERLINE_THICKNESS: 1202 autoCorrectionUnderlineThickness = in.readFloat( 1203 RemoteViewsProto.CharSequence.Span 1204 .Suggestion.AUTO_CORRECTION_UNDERLINE_THICKNESS); 1205 break; 1206 case (int) RemoteViewsProto.CharSequence.Span 1207 .Suggestion.GRAMMAR_ERROR_UNDERLINE_COLOR: 1208 grammarErrorUnderlineColor = in.readInt( 1209 RemoteViewsProto.CharSequence.Span 1210 .Suggestion.GRAMMAR_ERROR_UNDERLINE_COLOR); 1211 break; 1212 case (int) RemoteViewsProto.CharSequence.Span 1213 .Suggestion.GRAMMAR_ERROR_UNDERLINE_THICKNESS: 1214 grammarErrorUnderlineThickness = in.readFloat( 1215 RemoteViewsProto.CharSequence.Span 1216 .Suggestion.GRAMMAR_ERROR_UNDERLINE_THICKNESS); 1217 break; 1218 default: 1219 Log.w("SuggestionSpan", 1220 "Unhandled field while reading SuggestionSpan " + "proto!\n" 1221 + ProtoUtils.currentFieldToString(in)); 1222 } 1223 } 1224 String[] suggestionsArray = new String[suggestions.size()]; 1225 suggestions.toArray(suggestionsArray); 1226 return new SuggestionSpan(suggestionsArray, flags, localeStringForCompatibility, 1227 languageTag, hashCode, easyCorrectUnderlineColor, easyCorrectUnderlineThickness, 1228 misspelledUnderlineColor, misspelledUnderlineThickness, 1229 autoCorrectionUnderlineColor, autoCorrectionUnderlineThickness, 1230 grammarErrorUnderlineColor, grammarErrorUnderlineThickness); 1231 } 1232 writeSuggestionSpanToProto(@onNull ProtoOutputStream out, SuggestionSpan span)1233 public static void writeSuggestionSpanToProto(@NonNull ProtoOutputStream out, 1234 SuggestionSpan span) { 1235 for (String suggestion : span.getSuggestions()) { 1236 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.SUGGESTIONS, suggestion); 1237 } 1238 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.FLAGS, span.getFlags()); 1239 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.LOCALE_STRING_FOR_COMPATIBILITY, 1240 span.getLocale()); 1241 if (span.getLocaleObject() != null) { 1242 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.LANGUAGE_TAG, 1243 span.getLocaleObject().toLanguageTag()); 1244 } 1245 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.HASH_CODE, span.hashCode()); 1246 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.EASY_CORRECT_UNDERLINE_COLOR, 1247 span.getEasyCorrectUnderlineColor()); 1248 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.EASY_CORRECT_UNDERLINE_THICKNESS, 1249 span.getEasyCorrectUnderlineThickness()); 1250 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.MISSPELLED_UNDERLINE_COLOR, 1251 span.getMisspelledUnderlineColor()); 1252 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.MISSPELLED_UNDERLINE_THICKNESS, 1253 span.getMisspelledUnderlineThickness()); 1254 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.AUTO_CORRECTION_UNDERLINE_COLOR, 1255 span.getAutoCorrectionUnderlineColor()); 1256 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.AUTO_CORRECTION_UNDERLINE_THICKNESS, 1257 span.getAutoCorrectionUnderlineThickness()); 1258 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.GRAMMAR_ERROR_UNDERLINE_COLOR, 1259 span.getGrammarErrorUnderlineColor()); 1260 out.write(RemoteViewsProto.CharSequence.Span.Suggestion.GRAMMAR_ERROR_UNDERLINE_THICKNESS, 1261 span.getGrammarErrorUnderlineThickness()); 1262 } 1263 createSuperscriptSpanFromProto(@onNull ProtoInputStream in)1264 public static SuperscriptSpan createSuperscriptSpanFromProto(@NonNull ProtoInputStream in) { 1265 return new SuperscriptSpan(); 1266 } 1267 writeSuperscriptSpanToProto(@onNull ProtoOutputStream out, SuperscriptSpan span)1268 public static void writeSuperscriptSpanToProto(@NonNull ProtoOutputStream out, 1269 SuperscriptSpan span) { 1270 } 1271 createTextAppearanceSpanFromProto(@onNull ProtoInputStream in)1272 public static TextAppearanceSpan createTextAppearanceSpanFromProto(@NonNull ProtoInputStream in) 1273 throws Exception { 1274 String familyName = null; 1275 int style = 0; 1276 int textSize = 0; 1277 ColorStateList textColor = null; 1278 ColorStateList textColorLink = null; 1279 int textFontWeight = 0; 1280 LocaleList textLocales = null; 1281 float shadowRadius = 0F; 1282 float shadowDx = 0F; 1283 float shadowDy = 0F; 1284 int shadowColor = 0; 1285 boolean hasElegantTextHeight = false; 1286 boolean elegantTextHeight = false; 1287 boolean hasLetterSpacing = false; 1288 float letterSpacing = 0F; 1289 String fontFeatureSettings = null; 1290 String fontVariationSettings = null; 1291 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1292 switch (in.getFieldNumber()) { 1293 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.FAMILY_NAME: 1294 familyName = in.readString( 1295 RemoteViewsProto.CharSequence.Span.TextAppearance.FAMILY_NAME); 1296 break; 1297 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.STYLE: 1298 style = in.readInt(RemoteViewsProto.CharSequence.Span.TextAppearance.STYLE); 1299 break; 1300 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_SIZE: 1301 textSize = in.readInt( 1302 RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_SIZE); 1303 break; 1304 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_COLOR: 1305 final long textColorToken = in.start( 1306 RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_COLOR); 1307 textColor = ColorStateList.createFromProto(in); 1308 in.end(textColorToken); 1309 break; 1310 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_COLOR_LINK: 1311 final long textColorLinkToken = in.start( 1312 RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_COLOR_LINK); 1313 textColorLink = ColorStateList.createFromProto(in); 1314 in.end(textColorLinkToken); 1315 break; 1316 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_FONT_WEIGHT: 1317 textFontWeight = in.readInt( 1318 RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_FONT_WEIGHT); 1319 break; 1320 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_LOCALE: 1321 textLocales = LocaleList.forLanguageTags(in.readString( 1322 RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_LOCALE)); 1323 break; 1324 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_RADIUS: 1325 shadowRadius = in.readFloat( 1326 RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_RADIUS); 1327 break; 1328 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_DX: 1329 shadowDx = in.readFloat( 1330 RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_DX); 1331 break; 1332 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_DY: 1333 shadowDy = in.readFloat( 1334 RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_DY); 1335 break; 1336 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_COLOR: 1337 shadowColor = in.readInt( 1338 RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_COLOR); 1339 break; 1340 case (int) RemoteViewsProto.CharSequence.Span 1341 .TextAppearance.HAS_ELEGANT_TEXT_HEIGHT_FIELD: 1342 hasElegantTextHeight = in.readBoolean( 1343 RemoteViewsProto.CharSequence.Span 1344 .TextAppearance.HAS_ELEGANT_TEXT_HEIGHT_FIELD); 1345 break; 1346 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.ELEGANT_TEXT_HEIGHT: 1347 elegantTextHeight = in.readBoolean( 1348 RemoteViewsProto.CharSequence.Span.TextAppearance.ELEGANT_TEXT_HEIGHT); 1349 break; 1350 case (int) RemoteViewsProto.CharSequence.Span 1351 .TextAppearance.HAS_LETTER_SPACING_FIELD: 1352 hasLetterSpacing = in.readBoolean( 1353 RemoteViewsProto.CharSequence.Span 1354 .TextAppearance.HAS_LETTER_SPACING_FIELD); 1355 break; 1356 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.LETTER_SPACING: 1357 letterSpacing = in.readFloat( 1358 RemoteViewsProto.CharSequence.Span.TextAppearance.LETTER_SPACING); 1359 break; 1360 case (int) RemoteViewsProto.CharSequence.Span.TextAppearance.FONT_FEATURE_SETTINGS: 1361 fontFeatureSettings = in.readString( 1362 RemoteViewsProto.CharSequence.Span 1363 .TextAppearance.FONT_FEATURE_SETTINGS); 1364 break; 1365 case (int) RemoteViewsProto.CharSequence.Span 1366 .TextAppearance.FONT_VARIATION_SETTINGS: 1367 fontVariationSettings = in.readString( 1368 RemoteViewsProto.CharSequence.Span 1369 .TextAppearance.FONT_VARIATION_SETTINGS); 1370 break; 1371 default: 1372 Log.w("TextAppearanceSpan", 1373 "Unhandled field while reading TextAppearanceSpan " + "proto!\n" 1374 + ProtoUtils.currentFieldToString(in)); 1375 } 1376 } 1377 return new TextAppearanceSpan(familyName, style, textSize, textColor, textColorLink, 1378 /* typeface= */ null, textFontWeight, textLocales, shadowRadius, shadowDx, shadowDy, 1379 shadowColor, hasElegantTextHeight, elegantTextHeight, hasLetterSpacing, 1380 letterSpacing, fontFeatureSettings, fontVariationSettings); 1381 } 1382 writeTextAppearanceSpanToProto(@onNull ProtoOutputStream out, TextAppearanceSpan span)1383 public static void writeTextAppearanceSpanToProto(@NonNull ProtoOutputStream out, 1384 TextAppearanceSpan span) { 1385 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.FAMILY_NAME, span.getFamily()); 1386 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.STYLE, span.getTextStyle()); 1387 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_SIZE, span.getTextSize()); 1388 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_FONT_WEIGHT, 1389 span.getTextFontWeight()); 1390 if (span.getTextLocales() != null) { 1391 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_LOCALE, 1392 span.getTextLocales().toLanguageTags()); 1393 } 1394 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_RADIUS, 1395 span.getShadowRadius()); 1396 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_DX, span.getShadowDx()); 1397 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_DY, span.getShadowDy()); 1398 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.SHADOW_COLOR, 1399 span.getShadowColor()); 1400 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.HAS_ELEGANT_TEXT_HEIGHT_FIELD, 1401 span.hasElegantTextHeight()); 1402 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.ELEGANT_TEXT_HEIGHT, 1403 span.isElegantTextHeight()); 1404 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.HAS_LETTER_SPACING_FIELD, 1405 span.hasLetterSpacing()); 1406 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.LETTER_SPACING, 1407 span.getLetterSpacing()); 1408 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.FONT_FEATURE_SETTINGS, 1409 span.getFontFeatureSettings()); 1410 out.write(RemoteViewsProto.CharSequence.Span.TextAppearance.FONT_VARIATION_SETTINGS, 1411 span.getFontVariationSettings()); 1412 if (span.getTextColor() != null) { 1413 final long textColorToken = out.start( 1414 RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_COLOR); 1415 span.getTextColor().writeToProto(out); 1416 out.end(textColorToken); 1417 } 1418 if (span.getLinkTextColor() != null) { 1419 final long textColorLinkToken = out.start( 1420 RemoteViewsProto.CharSequence.Span.TextAppearance.TEXT_COLOR_LINK); 1421 span.getLinkTextColor().writeToProto(out); 1422 out.end(textColorLinkToken); 1423 } 1424 } 1425 createTtsSpanFromProto(@onNull ProtoInputStream in)1426 public static TtsSpan createTtsSpanFromProto(@NonNull ProtoInputStream in) throws Exception { 1427 String type = null; 1428 PersistableBundle args = null; 1429 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1430 switch (in.getFieldNumber()) { 1431 case (int) RemoteViewsProto.CharSequence.Span.Tts.TYPE: 1432 type = in.readString(RemoteViewsProto.CharSequence.Span.Tts.TYPE); 1433 break; 1434 case (int) RemoteViewsProto.CharSequence.Span.Tts.ARGS: 1435 final byte[] data = in.readString( 1436 RemoteViewsProto.CharSequence.Span.Tts.ARGS).getBytes(); 1437 args = PersistableBundle.readFromStream(new ByteArrayInputStream(data)); 1438 break; 1439 default: 1440 Log.w("TtsSpan", "Unhandled field while reading TtsSpan " + "proto!\n" 1441 + ProtoUtils.currentFieldToString(in)); 1442 } 1443 } 1444 return new TtsSpan(type, args); 1445 } 1446 writeTtsSpanToProto(@onNull ProtoOutputStream out, TtsSpan span)1447 public static void writeTtsSpanToProto(@NonNull ProtoOutputStream out, TtsSpan span) { 1448 out.write(RemoteViewsProto.CharSequence.Span.Tts.TYPE, span.getType()); 1449 if (span.getArgs() != null) { 1450 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 1451 try { 1452 span.getArgs().writeToStream(buf); 1453 } catch (IOException e) { 1454 throw new RuntimeException(e); 1455 } 1456 out.write(RemoteViewsProto.CharSequence.Span.Tts.ARGS, buf.toString(UTF_8)); 1457 } 1458 } 1459 createTypefaceSpanFromProto(@onNull ProtoInputStream in)1460 public static TypefaceSpan createTypefaceSpanFromProto(@NonNull ProtoInputStream in) 1461 throws Exception { 1462 String family = null; 1463 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1464 switch (in.getFieldNumber()) { 1465 case (int) RemoteViewsProto.CharSequence.Span.Typeface.FAMILY: 1466 family = in.readString(RemoteViewsProto.CharSequence.Span.Typeface.FAMILY); 1467 break; 1468 default: 1469 Log.w("TypefaceSpan", "Unhandled field while reading" + " TypefaceSpan proto!\n" 1470 + ProtoUtils.currentFieldToString(in)); 1471 } 1472 } 1473 return new TypefaceSpan(family); 1474 } 1475 writeTypefaceSpanToProto(@onNull ProtoOutputStream out, TypefaceSpan span)1476 public static void writeTypefaceSpanToProto(@NonNull ProtoOutputStream out, TypefaceSpan span) { 1477 out.write(RemoteViewsProto.CharSequence.Span.Typeface.FAMILY, span.getFamily()); 1478 } 1479 createURLSpanFromProto(@onNull ProtoInputStream in)1480 public static URLSpan createURLSpanFromProto(@NonNull ProtoInputStream in) throws Exception { 1481 String url = null; 1482 while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 1483 switch (in.getFieldNumber()) { 1484 case (int) RemoteViewsProto.CharSequence.Span.Url.URL: 1485 url = in.readString(RemoteViewsProto.CharSequence.Span.Url.URL); 1486 break; 1487 default: 1488 Log.w("URLSpan", "Unhandled field while reading" + " URLSpan proto!\n" 1489 + ProtoUtils.currentFieldToString(in)); 1490 } 1491 } 1492 return new URLSpan(url); 1493 } 1494 writeURLSpanToProto(@onNull ProtoOutputStream out, URLSpan span)1495 public static void writeURLSpanToProto(@NonNull ProtoOutputStream out, URLSpan span) { 1496 out.write(RemoteViewsProto.CharSequence.Span.Url.URL, span.getURL()); 1497 } 1498 createUnderlineSpanFromProto(@onNull ProtoInputStream in)1499 public static UnderlineSpan createUnderlineSpanFromProto(@NonNull ProtoInputStream in) { 1500 return new UnderlineSpan(); 1501 } 1502 writeUnderlineSpanToProto(@onNull ProtoOutputStream out, UnderlineSpan span)1503 public static void writeUnderlineSpanToProto(@NonNull ProtoOutputStream out, 1504 UnderlineSpan span) { 1505 } 1506 } 1507