| # 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. |