/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.analytics; import android.os.Build; import android.util.Log; import android.view.MotionEvent; import java.util.ArrayList; import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session; import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.PhoneEvent; import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.SensorEvent; import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.TouchEvent; /** * Collects touch, sensor and phone events and converts the data to * TouchAnalyticsProto.Session. */ public class SensorLoggerSession { private static final String TAG = "SensorLoggerSession"; private final long mStartTimestampMillis; private final long mStartSystemTimeNanos; private long mEndTimestampMillis; private int mType; private ArrayList mMotionEvents = new ArrayList<>(); private ArrayList mSensorEvents = new ArrayList<>(); private ArrayList mPhoneEvents = new ArrayList<>(); private int mTouchAreaHeight; private int mTouchAreaWidth; private int mResult = Session.UNKNOWN; public SensorLoggerSession(long startTimestampMillis, long startSystemTimeNanos) { mStartTimestampMillis = startTimestampMillis; mStartSystemTimeNanos = startSystemTimeNanos; mType = Session.REAL; } public void setType(int type) { mType = type; } public void end(long endTimestampMillis, int result) { mResult = result; mEndTimestampMillis = endTimestampMillis; if (DataCollector.DEBUG) { Log.d(TAG, "Ending session result=" + result + " it lasted for " + (float) (mEndTimestampMillis - mStartTimestampMillis) / 1000f + "s"); } } public void addMotionEvent(MotionEvent motionEvent) { TouchEvent event = motionEventToProto(motionEvent); mMotionEvents.add(event); } public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) { SensorEvent event = sensorEventToProto(eventOrig, systemTimeNanos); mSensorEvents.add(event); } public void addPhoneEvent(int eventType, long systemTimeNanos) { PhoneEvent event = phoneEventToProto(eventType, systemTimeNanos); mPhoneEvents.add(event); } @Override public String toString() { final StringBuilder sb = new StringBuilder("Session{"); sb.append("mStartTimestampMillis=").append(mStartTimestampMillis); sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos); sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis); sb.append(", mResult=").append(mResult); sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight); sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth); sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]"); sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]"); sb.append(", mPhoneEvents=[size=").append(mPhoneEvents.size()).append("]"); sb.append('}'); return sb.toString(); } public Session toProto() { Session proto = new Session(); proto.setStartTimestampMillis(mStartTimestampMillis); proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis); proto.setBuild(Build.FINGERPRINT); proto.setResult(mResult); proto.setType(mType); proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents); proto.touchEvents = mMotionEvents.toArray(proto.touchEvents); proto.phoneEvents = mPhoneEvents.toArray(proto.phoneEvents); proto.setTouchAreaWidth(mTouchAreaWidth); proto.setTouchAreaHeight(mTouchAreaHeight); return proto; } private PhoneEvent phoneEventToProto(int eventType, long sysTimeNanos) { PhoneEvent proto = new PhoneEvent(); proto.setType(eventType); proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos); return proto; } private SensorEvent sensorEventToProto(android.hardware.SensorEvent ev, long sysTimeNanos) { SensorEvent proto = new SensorEvent(); proto.setType(ev.sensor.getType()); proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos); proto.setTimestamp(ev.timestamp); proto.values = ev.values.clone(); return proto; } private TouchEvent motionEventToProto(MotionEvent ev) { int count = ev.getPointerCount(); TouchEvent proto = new TouchEvent(); proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos); proto.setAction(ev.getActionMasked()); proto.setActionIndex(ev.getActionIndex()); proto.pointers = new TouchEvent.Pointer[count]; for (int i = 0; i < count; i++) { TouchEvent.Pointer p = new TouchEvent.Pointer(); p.setX(ev.getX(i)); p.setY(ev.getY(i)); p.setSize(ev.getSize(i)); p.setPressure(ev.getPressure(i)); p.setId(ev.getPointerId(i)); proto.pointers[i] = p; } return proto; } public void setTouchArea(int width, int height) { mTouchAreaWidth = width; mTouchAreaHeight = height; } public int getResult() { return mResult; } public long getStartTimestampMillis() { return mStartTimestampMillis; } }