1# Clock Plugins 2 3## Introduction 4 5The clock appearing on the lock screen and always on display (AOD) can be 6customized via the ClockPlugin plugin interface. 7 8## System Health 9 10Clocks are high risk for battery consumption and screen burn-in because they 11modify the UI of AOD. 12 13To reduce battery consumption, it is recommended to 14target a maximum on-pixel-ratio (OPR) of 5%. Clocks that are composed of 15large blocks of color that cause the OPR to exceed 5% should be avoided. 16 17To prevent screen burn-in, clocks should not be composed of large solid 18blocks of color, and the clock should be moved around the screen to 19distribute the on pixels across a large number of pixels. Software 20burn-in testing is a good starting point to assess the pixel shifting 21(clock movement) scheme and shape of the clock. 22 23### Software Burn-In Test 24 25The goal is to look for bright spots in the luminosity average over a period of 26time. It is difficult to define a threshold where burn-in will occur. It is, 27therefore, recommended to compare against an element on AOD that is known not 28to cause problems. 29 30For clock face that contain color, it is recommended to use an all white 31version of the face. Since white has the highest luminosity, this version of 32the clock face represents the worst case scenario. 33 34To start, generate a sequence of screenshots for each minute over a 12 hr interval. 35 36``` 37serial = '84TY004MS' # serial number for the device 38count = 1 39t = datetime.datetime(2019, 1, 1) 40stop = t + datetime.timedelta(hours=12) 41if not os.path.exists(OUTPUT_FOLDER): 42 raise RuntimeError('output folder "%s" does not exist' % OUTPUT_FOLDER) 43while t <= stop: 44 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'))) 45 os.system('adb -s %s shell screencap -p > %s/screencap_%06d.png' % (serial, OUTPUT_FOLDER, count)) 46 t += datetime.timedelta(minutes=1) 47 count += 1 48``` 49 50Average the luminosity of the screenshots. 51 52``` 53#!python 54import numpy 55import scipy.ndimage 56from imageio import imread, imwrite 57import matplotlib.pylab as plt 58import os 59import os.path 60 61def images(path): 62 return [os.path.join(path, name) for name in os.listdir(path) if name.endswith('.png')] 63 64def average(images): 65 AVG = None 66 for name in images: 67 IM = scipy.ndimage.imread(name, mode='L') 68 A = numpy.array(IM, dtype=numpy.double) 69 if AVG is None: 70 AVG = A 71 else: 72 AVG += A 73 AVG /= len(images) 74 return numpy.array(AVG, dtype=numpy.uint8) 75 76def main(path): 77 ims = images(path) 78 if len(ims) == 0: 79 raise ValueError("folder '%s' doesn't contain any png files" % path) 80 AVG = average(ims) 81 imwrite('average.png', AVG) 82 plt.imshow(AVG) 83 plt.show() 84 85if __name__=='__main__': 86 import sys 87 main(sys.argv[1]) 88``` 89 90Look for bright spots in the luminosity average. If bright spots are found, 91action should be taken to change the shape of the clock face or increase the 92amount of pixel shifting. 93