1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15package com.android.systemui.statusbar.policy; 16 17import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_NUM_STATUS_ICONS; 18import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_ICONS; 19import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.STATUS_BAR_ICONS_CHANGED; 20import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION; 21 22import android.content.Context; 23import android.metrics.LogMaker; 24import android.os.Handler; 25import android.os.Looper; 26import android.support.annotation.VisibleForTesting; 27import android.util.ArraySet; 28 29import com.android.internal.logging.MetricsLogger; 30 31import java.util.Arrays; 32import java.util.List; 33 34public class IconLoggerImpl implements IconLogger { 35 36 // Minimum ms between log statements. 37 // NonFinalForTesting 38 @VisibleForTesting 39 protected static long MIN_LOG_INTERVAL = 1000; 40 41 private final Context mContext; 42 private final Handler mHandler; 43 private final MetricsLogger mLogger; 44 private final ArraySet<String> mIcons = new ArraySet<>(); 45 private final List<String> mIconIndex; 46 private long mLastLog = System.currentTimeMillis(); 47 48 public IconLoggerImpl(Context context, Looper bgLooper, MetricsLogger logger) { 49 mContext = context; 50 mHandler = new Handler(bgLooper); 51 mLogger = logger; 52 String[] icons = mContext.getResources().getStringArray( 53 com.android.internal.R.array.config_statusBarIcons); 54 mIconIndex = Arrays.asList(icons); 55 doLog(); 56 } 57 58 @Override 59 public void onIconShown(String tag) { 60 synchronized (mIcons) { 61 if (mIcons.contains(tag)) return; 62 mIcons.add(tag); 63 } 64 if (!mHandler.hasCallbacks(mLog)) { 65 mHandler.postDelayed(mLog, MIN_LOG_INTERVAL); 66 } 67 } 68 69 @Override 70 public void onIconHidden(String tag) { 71 synchronized (mIcons) { 72 if (!mIcons.contains(tag)) return; 73 mIcons.remove(tag); 74 } 75 if (!mHandler.hasCallbacks(mLog)) { 76 mHandler.postDelayed(mLog, MIN_LOG_INTERVAL); 77 } 78 } 79 80 private void doLog() { 81 long time = System.currentTimeMillis(); 82 long timeSinceLastLog = time - mLastLog; 83 mLastLog = time; 84 85 ArraySet<String> icons; 86 synchronized (mIcons) { 87 icons = new ArraySet<>(mIcons); 88 } 89 mLogger.write(new LogMaker(STATUS_BAR_ICONS_CHANGED) 90 .setType(TYPE_ACTION) 91 .setLatency(timeSinceLastLog) 92 .addTaggedData(FIELD_NUM_STATUS_ICONS, icons.size()) 93 .addTaggedData(FIELD_STATUS_ICONS, getBitField(icons))); 94 } 95 96 private int getBitField(ArraySet<String> icons) { 97 int iconsVisible = 0; 98 for (String icon : icons) { 99 int index = mIconIndex.indexOf(icon); 100 if (index >= 0) { 101 iconsVisible |= (1 << index); 102 } 103 } 104 return iconsVisible; 105 } 106 107 private final Runnable mLog = this::doLog; 108} 109