Dial development in WearOS Offload Mode 1

     offload refers to the screen rendering process by bg SidekickService, without rendering ap, this will save power consumption, long standby watch increases, retaining only the basic functions of the motion sensor, the motion mode is not turned on / GPS / WIFI / HR lamp module , the power consumption can save about 10%.

Rendering a dial in the watch .WearOS offload mode, it is drawn by BG. Conditions that dial into the offload watch dial is in the dim light mode and in Decomposable.

In order to satisfy the above conditions, it is necessary to develop dial to do the following configuration:

  a.manifest mera-data is increased DecompositionWatchFaceService

        <meta-data
                android:name="com.google.android.wearable.watchface.decomposable"
                android:value="true" />

b.updateDecomposition。

     UpdateDecomposition must be called to generate a valid WatchFaceDecomposition, otherwise the system is considered ordinary dial. It is a common method

    1. direct successor DecompositionWatchFaceService achieve buildDecomposition method.

   2 can also customize CanvasWatchFaceService, but must implement WatchFaceDecomposition displayable by updateDecomposition and notification system.

c. resource requirements.

    Under offload mode dial display font, the string must be presented in the form of "picture matting", for example, you want to show the number 1, to be deducted from digital pictures 1 font resource (FontComponent), the string is first converted into display BG drawable through the drawing, thus involving the dial string translation suggestions with complex data, because the complex data itself contains drawable, Home drawable be converted into the display dial ImageComponent convenience. Resources must be a bitmap image format, and must be RGB332, the dial can display up to 16 colors, does not support carry serrated, anti-burn-in mechanisms to continue to take effect in this mode.

II. How to confirm whether the watch successfully entered offload mode.

See addition AmbientService, SidekickService the log, but also can directly see the system power wake status, such as:

# dumpsys power | grep -i wake
    no_cached_wake_locks=true
  mWakefulness=Dozing
  mWakefulnessChanging=false
  mWakeLockSummary=0x40
  mLastWakeTime=45074118 (11793 ms ago)
  mHoldingWakeLockSuspendBlocker=false
  mWakeUpWhenPluggedOrUnpluggedConfig=true
  mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig=false
  mDrawWakeLockOverrideFromSidekick=true
  mDoubleTapWakeEnabled=false
Wake Locks: size=1
  DOZE_WAKE_LOCK                 'DreamManagerService' ACQ=-1s396ms (uid=1000 pid=1752)
  PowerManagerService.WakeLocks: ref count=0
  mGravitySensor={Sensor name="gravity  Non-wakeup", vendor="qualcomm", version=1, type=9, maxRange=1.0, resolution=0.1, power=0.515, minDelay=20000}

When SidekickService. MShouldControlDisplay is true, the value is also true, in a state of holding the screen STATE_DOZE_SUSPEND: The display is dozing in a suspended low power state; it is still on but the CPU is not updating it.

SidekickService calculates the buildDecomposition WatchFaceDecomposition returned used Components (), and parse each Components
of the display area, home to the last call replaceWatchFaceComponents update.

03-09 17:18:45.329  1752  1911 I SidekickService: endDisplayLocked()
03-09 17:18:45.359  1752  1911 D SidekickService:    ... endDisplay returns void
03-09 17:18:51.765  2390  4681 I SidekickManager: clearWatchFace called:
03-09 17:18:51.765  1752  1775 D SidekickService: resetLocked()
03-09 17:18:51.989  2390  4681 I SidekickManager: sendWatchFaceImpl(): watchFace = com.google.android.clockwork.decomposablewatchface.WatchFaceDecomposition@6673f0c forTWM = false
03-09 17:18:52.099  1752  1775 D SidekickService: sendWatchFaceComponents called: watchFace = com.google.android.clockwork.decomposablewatchface.WatchFaceDecomposition@468521shouldReplace = true
03-09 17:18:52.100  1752  1775 D SidekickService: sendWatchFaceLocked(): shouldReplace = true, mSidekickIsControlling = false, 8 images, 0 fonts, 0 numbers, 0 proportionalFonts, 0 strings
03-09 17:18:52.101  1752  1775 D SidekickService: ISidekickGraphics#beginResources()...
03-09 17:18:52.122  1752  1775 D SidekickServiceUtils: bitmapFromDrawable: Returning bitmap directly
03-09 17:18:52.208  1752  1775 D SidekickService: sendBitmapsLocked(): bounds = RectF(0.0, 0.0, 1.0, 1.0), drawableInfo = {.id = 2, .width = 338, .height = 412, .display = true, .offsetX = 0.0, .offsetY = 0.0, .rotationInfo = {.hasRotation = false, .pivotX = 0.0, .pivotY = 0.0, .degreesPerDay = 0.0, .degreesPerStep = 0.0, .zeroDegreesTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .transformInfo = {.transformed = false, .flipX = false, .flipY = false, .flip45 = false, .scaleX = 0.0, .scaleY = 0.0}, .type = GENERIC, .blink = {.blinking = false, .periodOnMs = 0.0, .periodOffMs = 0.0, .startTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .zOrder = 2, .displayInTwm = true}, image.size() = 1462
03-09 17:18:52.270  1752  1775 D SidekickService: sendBitmapsLocked(): status = 0, bytesUsed = 840
03-09 17:18:52.274  1752  1775 D SidekickServiceUtils: bitmapFromDrawable: Returning bitmap directly
03-09 17:18:52.275  1752  1775 D SidekickService: sendBitmapsLocked(): bounds = RectF(0.0, 0.0, 0.088757396, 0.07281554), drawableInfo = {.id = 10, .width = 30, .height = 30, .display = true, .offsetX = 0.0, .offsetY = 0.0, .rotationInfo = {.hasRotation = false, .pivotX = 0.0, .pivotY = 0.0, .degreesPerDay = 0.0, .degreesPerStep = 0.0, .zeroDegreesTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .transformInfo = {.transformed = false, .flipX = false, .flipY = false, .flip45 = false, .scaleX = 0.0, .scaleY = 0.0}, .type = GENERIC, .blink = {.blinking = false, .periodOnMs = 0.0, .periodOffMs = 0.0, .startTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .zOrder = 3, .displayInTwm = true}, image.size() = 131
03-09 17:18:52.279  1752  1775 D SidekickService: sendBitmapsLocked(): status = 0, bytesUsed = 75
03-09 17:18:52.279  1752  1775 D SidekickServiceUtils: bitmapFromDrawable: Returning bitmap directly
03-09 17:18:52.281  1752  1775 D SidekickService: sendBitmapsLocked(): bounds = RectF(0.9112426, 0.0, 1.0, 0.07281554), drawableInfo = {.id = 11, .width = 30, .height = 30, .display = true, .offsetX = 308.0, .offsetY = 0.0, .rotationInfo = {.hasRotation = false, .pivotX = 0.0, .pivotY = 0.0, .degreesPerDay = 0.0, .degreesPerStep = 0.0, .zeroDegreesTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .transformInfo = {.transformed = false, .flipX = false, .flipY = false, .flip45 = false, .scaleX = 0.0, .scaleY = 0.0}, .type = GENERIC, .blink = {.blinking = false, .periodOnMs = 0.0, .periodOffMs = 0.0, .startTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .zOrder = 3, .displayInTwm = true}, image.size() = 131
03-09 17:18:52.282  1752  1775 D SidekickService: sendBitmapsLocked(): status = 0, bytesUsed = 75
03-09 17:18:52.283  1752  1775 D SidekickServiceUtils: bitmapFromDrawable: Returning bitmap directly
03-09 17:18:52.286  1752  1775 D SidekickService: sendBitmapsLocked(): bounds = RectF(0.0, 0.92718446, 0.088757396, 1.0), drawableInfo = {.id = 12, .width = 30, .height = 30, .display = true, .offsetX = 0.0, .offsetY = 382.0, .rotationInfo = {.hasRotation = false, .pivotX = 0.0, .pivotY = 0.0, .degreesPerDay = 0.0, .degreesPerStep = 0.0, .zeroDegreesTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .transformInfo = {.transformed = false, .flipX = false, .flipY = false, .flip45 = false, .scaleX = 0.0, .scaleY = 0.0}, .type = GENERIC, .blink = {.blinking = false, .periodOnMs = 0.0, .periodOffMs = 0.0, .startTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .zOrder = 3, .displayInTwm = true}, image.size() = 131
03-09 17:18:52.289  1752  1775 D SidekickService: sendBitmapsLocked(): status = 0, bytesUsed = 75
03-09 17:18:52.290  1752  1775 D SidekickServiceUtils: bitmapFromDrawable: Returning bitmap directly
03-09 17:18:52.291  1752  1775 D SidekickService: sendBitmapsLocked(): bounds = RectF(0.9112426, 0.92718446, 1.0, 1.0), drawableInfo = {.id = 13, .width = 30, .height = 30, .display = true, .offsetX = 308.0, .offsetY = 382.0, .rotationInfo = {.hasRotation = false, .pivotX = 0.0, .pivotY = 0.0, .degreesPerDay = 0.0, .degreesPerStep = 0.0, .zeroDegreesTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .transformInfo = {.transformed = false, .flipX = false, .flipY = false, .flip45 = false, .scaleX = 0.0, .scaleY = 0.0}, .type = GENERIC, .blink = {.blinking = false, .periodOnMs = 0.0, .periodOffMs = 0.0, .startTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .zOrder = 3, .displayInTwm = true}, image.size() = 131
03-09 17:18:52.293  1752  1775 D SidekickService: sendBitmapsLocked(): status = 0, bytesUsed = 75
03-09 17:18:52.295  1752  1775 D SidekickServiceUtils: bitmapFromDrawable: Returning bitmap directly
03-09 17:18:52.296  1752  1775 D SidekickService: sendBitmapsLocked(): bounds = RectF(0.4704142, 0.47572815, 0.5295858, 0.52427185), drawableInfo = {.id = 14, .width = 20, .height = 20, .display = true, .offsetX = 159.0, .offsetY = 196.0, .rotationInfo = {.hasRotation = false, .pivotX = 0.0, .pivotY = 0.0, .degreesPerDay = 0.0, .degreesPerStep = 0.0, .zeroDegreesTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .transformInfo = {.transformed = false, .flipX = false, .flipY = false, .flip45 = false, .scaleX = 0.0, .scaleY = 0.0}, .type = GENERIC, .blink = {.blinking = false, .periodOnMs = 0.0, .periodOffMs = 0.0, .startTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .zOrder = 3, .displayInTwm = true}, image.size() = 143
03-09 17:18:52.298  1752  1775 D SidekickService: sendBitmapsLocked(): status = 0, bytesUsed = 60
03-09 17:18:52.299  1752  1775 D SidekickServiceUtils: bitmapFromDrawable: Returning bitmap directly
03-09 17:18:52.303  1752  1775 D SidekickService: sendBitmapsLocked(): bounds = RectF(0.46745563, 0.2669903, 0.5325444, 0.526699), drawableInfo = {.id = 15, .width = 22, .height = 107, .display = true, .offsetX = 158.0, .offsetY = 110.0, .rotationInfo = {.hasRotation = true, .pivotX = 11.0, .pivotY = 96.0, .degreesPerDay = 518400.0, .degreesPerStep = 6.0, .zeroDegreesTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 60000}}, .transformInfo = {.transformed = false, .flipX = false, .flipY = false, .flip45 = false, .scaleX = 0.0, .scaleY = 0.0}, .type = ROTATING, .blink = {.blinking = false, .periodOnMs = 0.0, .periodOffMs = 0.0, .startTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .zOrder = 4, .displayInTwm = true}, image.size() = 241
03-09 17:18:52.306  1752  1775 D SidekickService: sendBitmapsLocked(): status = 0, bytesUsed = 2897
03-09 17:18:52.307  1752  1775 D SidekickServiceUtils: bitmapFromDrawable: Returning bitmap directly
03-09 17:18:52.309  1752  1775 D SidekickService: sendBitmapsLocked(): bounds = RectF(0.0, 0.0, 0.0027173914, 0.002232143), drawableInfo = {.id = 100000, .width = 1, .height = 1, .display = true, .offsetX = 0.0, .offsetY = 0.0, .rotationInfo = {.hasRotation = false, .pivotX = 0.0, .pivotY = 0.0, .degreesPerDay = 0.0, .degreesPerStep = 0.0, .zeroDegreesTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .transformInfo = {.transformed = false, .flipX = false, .flipY = false, .flip45 = false, .scaleX = 0.0, .scaleY = 0.0}, .type = GENERIC, .blink = {.blinking = false, .periodOnMs = 0.0, .periodOffMs = 0.0, .startTime = {.daysSinceLocalEpoch = 0, .msSinceMidnight = 0}}, .zOrder = 5, .displayInTwm = true}, image.size() = 84
03-09 17:18:52.310  1752  1775 D SidekickService: sendBitmapsLocked(): status = 0, bytesUsed = 18
03-09 17:18:52.310  1752  1775 D SidekickService: ISidekickGraphics#endResources()...
03-09 17:21:32.580  1752  2548 D SidekickService: sendBitmapsLocked(): status = 0, bytesUsed = 155
03-09 17:21:32.580  1752  2548 D SidekickService: ISidekickGraphics#endResources()...
03-09 17:21:32.812  2390  2390 D SidekickManagerAsync: replaceWatchFaceComponents(): Callback#onResult(): 0
03-09 17:21:32.819  1752  2548 D SidekickService: setShouldControlDisplay called: true
03-09 17:21:32.875  1752  1911 I SidekickService: beginDisplayLocked(): DOZE_SUSPEND
03-09 17:21:32.965  1752  1911 D SidekickService:    ... beginDisplay result: 0 for halPower: 1
(standard input):17378:03-09 17:21:26.048  1752 19744 I AmbientService: [6e93f94] Showing watch face in offload mode, canceling alarm.

replaceWatchFaceComponents resources will be checked if the resource format is wrong, there will be related error message prompts, such as

03-09 17:32:01.810  2390  2390 D SidekickManagerAsync: sendWatchFace(): Callback#onResult(): 2
03-09 17:32:09.808  1752  1752 D SidekickService: setShouldControlDisplay called: false
03-09 17:32:09.861  2390  7074 I SidekickManager: replaceWatchFaceComponentsImpl(): watchFace = com.google.android.clockwork.decomposablewatchface.WatchFaceDecomposition@f4d00e1
03-09 17:32:09.862  1752 26357 D SidekickService: sendWatchFaceComponents called: watchFace = com.google.android.clockwork.decomposablewatchface.WatchFaceDecomposition@dfbff84shouldReplace = false
03-09 17:32:09.864  1752 26357 W SidekickService: Ignoring partial update to an invalid watchface
03-09 17:32:09.923  2390  2390 D SidekickManagerAsync: replaceWatchFaceComponents(): Callback#onResult(): 2

replaceWatchFaceComponents (): Callback # onResult (): returns 2, indicates an invalid dial.

Question three .Decomposable display pointer of the dial.

   Enter offload mode.

Only display picture (if provided with the original rectangular area pointer ImageComponent inconsistent, the display will not be enlarged / reduced), based on this rule, when the region is inconsistent with the original RECF imageComponent provided to only 1. Dial the coordinates of the upper left corner valid. This is described in the Google Wear Partner Doc_ Decomposable Watch Face API documentation.

2. The rotation of the pointer shaft is always the central position of the drawing region BG (BG five drawing reference herein). Based on this rule, when the development Decomposable Watchface dial, the pointer must be "spin" something BG secured to the center position.

3. Even if satisfying the above two points, found found, the pointer during rotation, "rotation" something is still visible position shifted. To reduce this problem, modify the shape of the pointer, the dial center position of a circular fixed ImageComponent circle, the circle placed above the hour and minute hands, a second hand into the top circle.

4. Because carry sawtooth mode does not support offload, the display vector can not only display the bitmap, there will inevitably rough edges, so that the UI showing, comprising circular, elliptical, circular arc as the arc gradient Some do fine. And try not to use color, find the measured color may be because the screen is dark, bright color screen, the easier the more flash.

When the pointer is displayed at 5.offload mode dial, you can not carry serrated, looks really bad, says Google may be able to optimize the version in the future, but at present can only be improved by adjusting the pointer display picture.

Fourth, the watch dial Decomposable product demand.

Because Decomposable dial can save power consumption, the project hopes to use Decomposable dial, but the pointer dial display effect is not good, after communication with the product, design, prefer the digital version of Decomposable dial. Issue digital version Decomposable dial to consider.

 1. The need for basic information display, basically decided to show hours, date, Sunday.

 2. Due to offload mode dial can only display ImageComponent, ComplicationComponent, FontComponent, NumberComponent. The presence of these component are drawable form, taking into account the watches international string translation issues, only to show the basis of the above information ComplicationComponent form.

3. The system comes with clock complex UI data is difficult to meet our requirements. If you want to meet product requirements, we need to customize complex data show the division, date, Sunday. To watch the development of the world clock, you can increase the complexity of the data in this app.

4. Verify that since we had to be able to define complex data refresh as expected.

Five, BG drawing area.

  Ambient entering the watch, in order to prevent a region of the screen causes the screen to appear bad block Steady, high-pass provides a "burn-proof" mechanism, the principle of the mechanism is a smaller area in an original display, in 1 to 2 minutes movement of the region within the time. Display area size is adjustable, but the specific adjustment rule is unclear, only know

2 * (10 + 2-DISPLAY_BURNIN_PIXEL_WIDTH * 2 + 2 * DISPLAY_BURNIN_PIXEL_HEIGHT not be greater than 255, and wherein DISPLAY_BURNIN_PIXEL_WIDTH DISPLAY_BURNIN_PIXEL_HEIGHT respectively subtracted when the anti-burn width, height.

For example, the original screen resolution of 368 * 448, DISPLAY_BURNIN_PIXEL_WIDTH = 30, DISPLAY_BURNIN_PIXEL_HEIGHT = 36. So in

Under ambient mode the actual display resolution 338 * 412 (screen burn preventing enabled).

logcat.01:1044:03-09 19:10:10.950033  1691  1732 D SidekickService: SidekickService#getCapabilities()
logcat.01:1067:03-09 19:10:11.002619   413  1733 D SKGHAL  : getCapabilities: Capabilities returned
logcat.01:1068:03-09 19:10:11.002643   413  1733 D SKGHAL  : getCapabilities: RGB bits        = [3,3,2]
logcat.01:1069:03-09 19:10:11.002663   413  1733 D SKGHAL  : getCapabilities: paletteSize      = 16
logcat.01:1070:03-09 19:10:11.002680   413  1733 D SKGHAL  : getCapabilities: operations       = 1102000b
logcat.01:1071:03-09 19:10:11.002698   413  1733 D SKGHAL  : getCapabilities: availMemory      = 49800
logcat.01:1072:03-09 19:10:11.002718   413  1733 D SKGHAL  : getCapabilities: (x, y)           = (338, 412)
logcat.01:1074:03-09 19:10:11.004113  1691  1732 D SidekickService: SidekickService#getCapabilities(): {.capabilities = 285343755, .displaySizeX = 338, .displaySizeY = 412}

 

Published 21 original articles · won praise 5 · views 30000 +

Guess you like

Origin blog.csdn.net/linchuanzhi_886/article/details/104757382