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