1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.systemui.analytics; 18 19 import android.os.Build; 20 import android.util.Log; 21 import android.view.MotionEvent; 22 23 import java.util.ArrayList; 24 25 import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session; 26 import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent; 27 import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.SensorEvent; 28 import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.TouchEvent; 29 30 /** 31 * Collects touch, sensor and phone events and converts the data to 32 * TouchAnalyticsProto.Session. 33 */ 34 public class SensorLoggerSession { 35 private static final String TAG = "SensorLoggerSession"; 36 37 private final long mStartTimestampMillis; 38 private final long mStartSystemTimeNanos; 39 40 private long mEndTimestampMillis; 41 private int mType; 42 43 private ArrayList<TouchEvent> mMotionEvents = new ArrayList<>(); 44 private ArrayList<SensorEvent> mSensorEvents = new ArrayList<>(); 45 private ArrayList<PhoneEvent> mPhoneEvents = new ArrayList<>(); 46 private int mTouchAreaHeight; 47 private int mTouchAreaWidth; 48 private int mResult = Session.UNKNOWN; 49 50 public SensorLoggerSession(long startTimestampMillis, long startSystemTimeNanos) { 51 mStartTimestampMillis = startTimestampMillis; 52 mStartSystemTimeNanos = startSystemTimeNanos; 53 mType = Session.REAL; 54 } 55 56 public void setType(int type) { 57 mType = type; 58 } 59 60 public void end(long endTimestampMillis, int result) { 61 mResult = result; 62 mEndTimestampMillis = endTimestampMillis; 63 64 if (DataCollector.DEBUG) { 65 Log.d(TAG, "Ending session result=" + result + " it lasted for " + 66 (float) (mEndTimestampMillis - mStartTimestampMillis) / 1000f + "s"); 67 } 68 } 69 70 public void addMotionEvent(MotionEvent motionEvent) { 71 TouchEvent event = motionEventToProto(motionEvent); 72 mMotionEvents.add(event); 73 } 74 75 public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) { 76 SensorEvent event = sensorEventToProto(eventOrig, systemTimeNanos); 77 mSensorEvents.add(event); 78 } 79 80 public void addPhoneEvent(int eventType, long systemTimeNanos) { 81 PhoneEvent event = phoneEventToProto(eventType, systemTimeNanos); 82 mPhoneEvents.add(event); 83 } 84 85 86 @Override 87 public String toString() { 88 final StringBuilder sb = new StringBuilder("Session{"); 89 sb.append("mStartTimestampMillis=").append(mStartTimestampMillis); 90 sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos); 91 sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis); 92 sb.append(", mResult=").append(mResult); 93 sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight); 94 sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth); 95 sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]"); 96 sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]"); 97 sb.append(", mPhoneEvents=[size=").append(mPhoneEvents.size()).append("]"); 98 sb.append('}'); 99 return sb.toString(); 100 } 101 102 public Session toProto() { 103 Session proto = new Session(); 104 proto.setStartTimestampMillis(mStartTimestampMillis); 105 proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis); 106 proto.setBuild(Build.FINGERPRINT); 107 proto.setResult(mResult); 108 proto.setType(mType); 109 proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents); 110 proto.touchEvents = mMotionEvents.toArray(proto.touchEvents); 111 proto.phoneEvents = mPhoneEvents.toArray(proto.phoneEvents); 112 proto.setTouchAreaWidth(mTouchAreaWidth); 113 proto.setTouchAreaHeight(mTouchAreaHeight); 114 return proto; 115 } 116 117 private PhoneEvent phoneEventToProto(int eventType, long sysTimeNanos) { 118 PhoneEvent proto = new PhoneEvent(); 119 proto.setType(eventType); 120 proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos); 121 return proto; 122 } 123 124 private SensorEvent sensorEventToProto(android.hardware.SensorEvent ev, long sysTimeNanos) { 125 SensorEvent proto = new SensorEvent(); 126 proto.setType(ev.sensor.getType()); 127 proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos); 128 proto.setTimestamp(ev.timestamp); 129 proto.values = ev.values.clone(); 130 return proto; 131 } 132 133 private TouchEvent motionEventToProto(MotionEvent ev) { 134 int count = ev.getPointerCount(); 135 TouchEvent proto = new TouchEvent(); 136 proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos); 137 proto.setAction(ev.getActionMasked()); 138 proto.setActionIndex(ev.getActionIndex()); 139 proto.pointers = new TouchEvent.Pointer[count]; 140 for (int i = 0; i < count; i++) { 141 TouchEvent.Pointer p = new TouchEvent.Pointer(); 142 p.setX(ev.getX(i)); 143 p.setY(ev.getY(i)); 144 p.setSize(ev.getSize(i)); 145 p.setPressure(ev.getPressure(i)); 146 p.setId(ev.getPointerId(i)); 147 proto.pointers[i] = p; 148 } 149 return proto; 150 } 151 152 public void setTouchArea(int width, int height) { 153 mTouchAreaWidth = width; 154 mTouchAreaHeight = height; 155 } 156 157 public int getResult() { 158 return mResult; 159 } 160 161 public long getStartTimestampMillis() { 162 return mStartTimestampMillis; 163 } 164 } 165