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 17package com.android.systemui.analytics; 18 19import android.os.Build; 20import android.util.Log; 21import android.view.MotionEvent; 22 23import java.util.ArrayList; 24 25import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session; 26import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.PhoneEvent; 27import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.SensorEvent; 28import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.TouchEvent; 29 30/** 31 * Collects touch, sensor and phone events and converts the data to 32 * TouchAnalyticsProto.Session. 33 */ 34public 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 end(long endTimestampMillis, int result) { 57 mResult = result; 58 mEndTimestampMillis = endTimestampMillis; 59 60 if (DataCollector.DEBUG) { 61 Log.d(TAG, "Ending session result=" + result + " it lasted for " + 62 (float) (mEndTimestampMillis - mStartTimestampMillis) / 1000f + "s"); 63 } 64 } 65 66 public void addMotionEvent(MotionEvent motionEvent) { 67 TouchEvent event = motionEventToProto(motionEvent); 68 mMotionEvents.add(event); 69 } 70 71 public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) { 72 SensorEvent event = sensorEventToProto(eventOrig, systemTimeNanos); 73 mSensorEvents.add(event); 74 } 75 76 public void addPhoneEvent(int eventType, long systemTimeNanos) { 77 PhoneEvent event = phoneEventToProto(eventType, systemTimeNanos); 78 mPhoneEvents.add(event); 79 } 80 81 82 @Override 83 public String toString() { 84 final StringBuilder sb = new StringBuilder("Session{"); 85 sb.append("mStartTimestampMillis=").append(mStartTimestampMillis); 86 sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos); 87 sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis); 88 sb.append(", mResult=").append(mResult); 89 sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight); 90 sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth); 91 sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]"); 92 sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]"); 93 sb.append(", mPhoneEvents=[size=").append(mPhoneEvents.size()).append("]"); 94 sb.append('}'); 95 return sb.toString(); 96 } 97 98 public Session toProto() { 99 Session proto = new Session(); 100 proto.setStartTimestampMillis(mStartTimestampMillis); 101 proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis); 102 proto.setBuild(Build.FINGERPRINT); 103 proto.setResult(mResult); 104 proto.setType(mType); 105 proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents); 106 proto.touchEvents = mMotionEvents.toArray(proto.touchEvents); 107 proto.phoneEvents = mPhoneEvents.toArray(proto.phoneEvents); 108 proto.setTouchAreaWidth(mTouchAreaWidth); 109 proto.setTouchAreaHeight(mTouchAreaHeight); 110 return proto; 111 } 112 113 private PhoneEvent phoneEventToProto(int eventType, long sysTimeNanos) { 114 PhoneEvent proto = new PhoneEvent(); 115 proto.setType(eventType); 116 proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos); 117 return proto; 118 } 119 120 private SensorEvent sensorEventToProto(android.hardware.SensorEvent ev, long sysTimeNanos) { 121 SensorEvent proto = new SensorEvent(); 122 proto.setType(ev.sensor.getType()); 123 proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos); 124 proto.setTimestamp(ev.timestamp); 125 proto.values = ev.values.clone(); 126 return proto; 127 } 128 129 private TouchEvent motionEventToProto(MotionEvent ev) { 130 int count = ev.getPointerCount(); 131 TouchEvent proto = new TouchEvent(); 132 proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos); 133 proto.setAction(ev.getActionMasked()); 134 proto.setActionIndex(ev.getActionIndex()); 135 proto.pointers = new TouchEvent.Pointer[count]; 136 for (int i = 0; i < count; i++) { 137 TouchEvent.Pointer p = new TouchEvent.Pointer(); 138 p.setX(ev.getX(i)); 139 p.setY(ev.getY(i)); 140 p.setSize(ev.getSize(i)); 141 p.setPressure(ev.getPressure(i)); 142 p.setId(ev.getPointerId(i)); 143 proto.pointers[i] = p; 144 } 145 return proto; 146 } 147 148 public void setTouchArea(int width, int height) { 149 mTouchAreaWidth = width; 150 mTouchAreaHeight = height; 151 } 152 153 public int getResult() { 154 return mResult; 155 } 156 157 public long getStartTimestampMillis() { 158 return mStartTimestampMillis; 159 } 160} 161