| # Clock Plugins |
| |
| ## Introduction |
| |
| The clock appearing on the lock screen and always on display (AOD) can be |
| customized via the ClockPlugin plugin interface. |
| |
| ## System Health |
| |
| Clocks are high risk for battery consumption and screen burn-in because they |
| modify the UI of AOD. |
| |
| To reduce battery consumption, it is recommended to |
| target a maximum on-pixel-ratio (OPR) of 5%. Clocks that are composed of |
| large blocks of color that cause the OPR to exceed 5% should be avoided. |
| |
| To prevent screen burn-in, clocks should not be composed of large solid |
| blocks of color, and the clock should be moved around the screen to |
| distribute the on pixels across a large number of pixels. Software |
| burn-in testing is a good starting point to assess the pixel shifting |
| (clock movement) scheme and shape of the clock. |
| |
| ### Software Burn-In Test |
| |
| The goal is to look for bright spots in the luminosity average over a period of |
| time. It is difficult to define a threshold where burn-in will occur. It is, |
| therefore, recommended to compare against an element on AOD that is known not |
| to cause problems. |
| |
| For clock face that contain color, it is recommended to use an all white |
| version of the face. Since white has the highest luminosity, this version of |
| the clock face represents the worst case scenario. |
| |
| To start, generate a sequence of screenshots for each minute over a 12 hr interval. |
| |
| ``` |
| serial = '84TY004MS' # serial number for the device |
| count = 1 |
| t = datetime.datetime(2019, 1, 1) |
| stop = t + datetime.timedelta(hours=12) |
| if not os.path.exists(OUTPUT_FOLDER): |
| raise RuntimeError('output folder "%s" does not exist' % OUTPUT_FOLDER) |
| while t <= stop: |
| os.system("adb -s %s shell 'date %s ; am broadcast -a android.intent.action.TIME_SET'" % (serial, t.strftime('%m%d%H%M%Y.%S'))) |
| os.system('adb -s %s shell screencap -p > %s/screencap_%06d.png' % (serial, OUTPUT_FOLDER, count)) |
| t += datetime.timedelta(minutes=1) |
| count += 1 |
| ``` |
| |
| Average the luminosity of the screenshots. |
| |
| ``` |
| #!python |
| import numpy |
| import scipy.ndimage |
| from imageio import imread, imwrite |
| import matplotlib.pylab as plt |
| import os |
| import os.path |
| |
| def images(path): |
| return [os.path.join(path, name) for name in os.listdir(path) if name.endswith('.png')] |
| |
| def average(images): |
| AVG = None |
| for name in images: |
| IM = scipy.ndimage.imread(name, mode='L') |
| A = numpy.array(IM, dtype=numpy.double) |
| if AVG is None: |
| AVG = A |
| else: |
| AVG += A |
| AVG /= len(images) |
| return numpy.array(AVG, dtype=numpy.uint8) |
| |
| def main(path): |
| ims = images(path) |
| if len(ims) == 0: |
| raise ValueError("folder '%s' doesn't contain any png files" % path) |
| AVG = average(ims) |
| imwrite('average.png', AVG) |
| plt.imshow(AVG) |
| plt.show() |
| |
| if __name__=='__main__': |
| import sys |
| main(sys.argv[1]) |
| ``` |
| |
| Look for bright spots in the luminosity average. If bright spots are found, |
| action should be taken to change the shape of the clock face or increase the |
| amount of pixel shifting. |