Home | History | Annotate | Download | only in docs
      1 # Clock Plugins
      2 
      3 ## Introduction
      4 
      5 The clock appearing on the lock screen and always on display (AOD) can be
      6 customized via the ClockPlugin plugin interface.
      7 
      8 ## System Health
      9 
     10 Clocks are high risk for battery consumption and screen burn-in because they
     11 modify the UI of AOD.
     12 
     13 To reduce battery consumption, it is recommended to
     14 target a maximum on-pixel-ratio (OPR) of 5%. Clocks that are composed of
     15 large blocks of color that cause the OPR to exceed 5% should be avoided.
     16 
     17 To prevent screen burn-in, clocks should not be composed of large solid
     18 blocks of color, and the clock should be moved around the screen to
     19 distribute the on pixels across a large number of pixels. Software
     20 burn-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 
     25 The goal is to look for bright spots in the luminosity average over a period of
     26 time. It is difficult to define a threshold where burn-in will occur. It is,
     27 therefore, recommended to compare against an element on AOD that is known not
     28 to cause problems.
     29 
     30 For clock face that contain color, it is recommended to use an all white
     31 version of the face. Since white has the highest luminosity, this version of
     32 the clock face represents the worst case scenario.
     33 
     34 To start, generate a sequence of screenshots for each minute over a 12 hr interval.
     35 
     36 ```
     37 serial = '84TY004MS' # serial number for the device
     38 count = 1
     39 t = datetime.datetime(2019, 1, 1)
     40 stop = t + datetime.timedelta(hours=12)
     41 if not os.path.exists(OUTPUT_FOLDER):
     42   raise RuntimeError('output folder "%s" does not exist' % OUTPUT_FOLDER)
     43 while 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 
     50 Average the luminosity of the screenshots.
     51 
     52 ```
     53 #!python
     54 import numpy
     55 import scipy.ndimage
     56 from imageio import imread, imwrite
     57 import matplotlib.pylab as plt
     58 import os
     59 import os.path
     60 
     61 def images(path):
     62   return [os.path.join(path, name) for name in os.listdir(path) if name.endswith('.png')]
     63 
     64 def 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 
     76 def 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 
     85 if __name__=='__main__':
     86   import sys
     87   main(sys.argv[1])
     88 ```
     89 
     90 Look for bright spots in the luminosity average. If bright spots are found,
     91 action should be taken to change the shape of the clock face or increase the
     92 amount of pixel shifting.
     93