13380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler/*
23380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * Copyright (C) 2012 The Android Open Source Project
33380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler *
43380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * Licensed under the Apache License, Version 2.0 (the "License"); you may not
53380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * use this file except in compliance with the License. You may obtain a copy of
63380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * the License at
73380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler *
83380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * http://www.apache.org/licenses/LICENSE-2.0
93380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler *
103380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * Unless required by applicable law or agreed to in writing, software
113380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
123380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
133380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * License for the specific language governing permissions and limitations under
143380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * the License.
153380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler */
163380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
173380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerpackage com.android.systemui.statusbar;
183380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
193380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport java.io.BufferedWriter;
203380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport java.io.FileDescriptor;
213380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport java.io.FileWriter;
223380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport java.io.IOException;
233380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport java.io.PrintWriter;
243380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport java.util.HashSet;
253380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport java.util.LinkedList;
263380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
273380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport android.os.Handler;
283380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport android.os.Message;
293380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport android.os.SystemClock;
303380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport android.util.Slog;
313380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerimport android.view.MotionEvent;
323380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
333380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler/**
343380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler * Convenience class for capturing gestures for later analysis.
353380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler */
363380534a62abf20b4509db6068ac02b1b880712fDaniel Sandlerpublic class GestureRecorder {
373380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public static final boolean DEBUG = true; // for now
383380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public static final String TAG = GestureRecorder.class.getSimpleName();
393380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
403380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public class Gesture {
413380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        public abstract class Record {
423380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            long time;
433380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            public abstract String toJson();
443380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
453380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        public class MotionEventRecord extends Record {
463380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            public MotionEvent event;
473380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            public MotionEventRecord(long when, MotionEvent event) {
483380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                this.time = when;
493380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                this.event = event.copy();
503380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
513380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            String actionName(int action) {
523380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                switch (action) {
533380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                    case MotionEvent.ACTION_DOWN:
543380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        return "down";
553380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                    case MotionEvent.ACTION_UP:
563380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        return "up";
573380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                    case MotionEvent.ACTION_MOVE:
583380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        return "move";
593380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                    case MotionEvent.ACTION_CANCEL:
603380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        return "cancel";
613380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                    default:
623380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        return String.valueOf(action);
633380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                }
643380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
653380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            public String toJson() {
66780d668bee92ecdef6e08d92fc227f92425a58c8Daniel Sandler                return String.format(
67780d668bee92ecdef6e08d92fc227f92425a58c8Daniel Sandler                        ("{\"type\":\"motion\", \"time\":%d, \"action\":\"%s\", "
68780d668bee92ecdef6e08d92fc227f92425a58c8Daniel Sandler                            + "\"x\":%.2f, \"y\":%.2f, \"s\":%.2f, \"p\":%.2f}"),
693380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        this.time,
703380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        actionName(this.event.getAction()),
713380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        this.event.getRawX(),
72780d668bee92ecdef6e08d92fc227f92425a58c8Daniel Sandler                        this.event.getRawY(),
73780d668bee92ecdef6e08d92fc227f92425a58c8Daniel Sandler                        this.event.getSize(),
74780d668bee92ecdef6e08d92fc227f92425a58c8Daniel Sandler                        this.event.getPressure()
753380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        );
763380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
773380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
783380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        public class TagRecord extends Record {
793380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            public String tag, info;
803380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            public TagRecord(long when, String tag, String info) {
813380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                this.time = when;
823380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                this.tag = tag;
833380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                this.info = info;
843380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
853380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            public String toJson() {
863380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                return String.format("{\"type\":\"tag\", \"time\":%d, \"tag\":\"%s\", \"info\":\"%s\"}",
873380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        this.time,
883380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        this.tag,
893380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        this.info
903380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                        );
913380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
923380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
933380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        private LinkedList<Record> mRecords = new LinkedList<Record>();
943380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        private HashSet<String> mTags = new HashSet<String>();
953380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        long mDownTime = -1;
963380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        boolean mComplete = false;
973380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
983380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        public void add(MotionEvent ev) {
993380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            mRecords.add(new MotionEventRecord(ev.getEventTime(), ev));
1003380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            if (mDownTime < 0) {
1013380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                mDownTime = ev.getDownTime();
1023380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            } else {
1033380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                if (mDownTime != ev.getDownTime()) {
104fa71962948092786c5190f39fd25ce3d55a4e287Daniel Sandler                    Slog.w(TAG, "Assertion failure in GestureRecorder: event downTime ("
1053380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                            +ev.getDownTime()+") does not match gesture downTime ("+mDownTime+")");
1063380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                }
1073380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
1083380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            switch (ev.getActionMasked()) {
1093380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                case MotionEvent.ACTION_UP:
1103380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                case MotionEvent.ACTION_CANCEL:
1113380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                    mComplete = true;
1123380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
1133380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
1143380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        public void tag(long when, String tag, String info) {
1153380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            mRecords.add(new TagRecord(when, tag, info));
1163380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            mTags.add(tag);
1173380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
1183380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        public boolean isComplete() {
1193380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            return mComplete;
1203380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
1213380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        public String toJson() {
1223380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            StringBuilder sb = new StringBuilder();
1233380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            boolean first = true;
1243380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            sb.append("[");
1253380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            for (Record r : mRecords) {
1263380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                if (!first) sb.append(", ");
1273380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                first = false;
1283380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                sb.append(r.toJson());
1293380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
1303380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            sb.append("]");
1313380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            return sb.toString();
1323380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
1333380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
1343380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1353380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    // -=-=-=-=-=-=-=-=-=-=-=-
1363380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1373380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    static final long SAVE_DELAY = 5000; // ms
1383380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    static final int SAVE_MESSAGE = 6351;
1393380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1403380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    private LinkedList<Gesture> mGestures;
1413380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    private Gesture mCurrentGesture;
1423380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    private int mLastSaveLen = -1;
1433380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    private String mLogfile;
1443380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1453380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    private Handler mHandler = new Handler() {
1463380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        @Override
1473380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        public void handleMessage(Message msg) {
1483380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            if (msg.what == SAVE_MESSAGE) {
1493380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                save();
1503380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
1513380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
1523380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    };
1533380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1543380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public GestureRecorder(String filename) {
1553380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        mLogfile = filename;
1563380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        mGestures = new LinkedList<Gesture>();
1573380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        mCurrentGesture = null;
1583380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
1593380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1603380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public void add(MotionEvent ev) {
1613380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        synchronized (mGestures) {
1623380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            if (mCurrentGesture == null || mCurrentGesture.isComplete()) {
1633380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                mCurrentGesture = new Gesture();
1643380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                mGestures.add(mCurrentGesture);
1653380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
1663380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            mCurrentGesture.add(ev);
1673380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
1683380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        saveLater();
1693380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
1703380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1713380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public void tag(long when, String tag, String info) {
1723380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        synchronized (mGestures) {
1733380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            if (mCurrentGesture == null) {
1743380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                mCurrentGesture = new Gesture();
1753380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                mGestures.add(mCurrentGesture);
1763380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
1773380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            mCurrentGesture.tag(when, tag, info);
1783380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
1793380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        saveLater();
1803380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
1813380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1823380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public void tag(long when, String tag) {
1833380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        tag(when, tag, null);
1843380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
1853380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1863380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public void tag(String tag) {
1873380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        tag(SystemClock.uptimeMillis(), tag, null);
1883380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
1893380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1903380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public void tag(String tag, String info) {
1913380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        tag(SystemClock.uptimeMillis(), tag, info);
1923380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
1933380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
1943380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    /**
1953380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler     * Generates a JSON string capturing all completed gestures.
1963380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler     * Not threadsafe; call with a lock.
1973380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler     */
1983380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public String toJsonLocked() {
1993380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        StringBuilder sb = new StringBuilder();
2003380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        boolean first = true;
2013380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        sb.append("[");
2023380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        int count = 0;
2033380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        for (Gesture g : mGestures) {
2043380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            if (!g.isComplete()) continue;
2053380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            if (!first) sb.append("," );
2063380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            first = false;
2073380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            sb.append(g.toJson());
2083380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            count++;
2093380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
2103380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        mLastSaveLen = count;
2113380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        sb.append("]");
2123380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        return sb.toString();
2133380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
2143380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
2153380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public String toJson() {
2163380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        String s;
2173380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        synchronized (mGestures) {
2183380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            s = toJsonLocked();
2193380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
2203380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        return s;
2213380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
2223380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
2233380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public void saveLater() {
2243380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        mHandler.removeMessages(SAVE_MESSAGE);
2253380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        mHandler.sendEmptyMessageDelayed(SAVE_MESSAGE, SAVE_DELAY);
2263380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
2273380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
2283380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public void save() {
2293380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        synchronized (mGestures) {
2303380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            try {
2313380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                BufferedWriter w = new BufferedWriter(new FileWriter(mLogfile, /*append=*/ true));
2323380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                w.append(toJsonLocked() + "\n");
2333380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                w.close();
2343380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                mGestures.clear();
2353380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                // If we have a pending gesture, push it back
23675fcac4eebdf7ff68a534e9af1664c571f40ef30Daniel Sandler                if (mCurrentGesture != null && !mCurrentGesture.isComplete()) {
2373380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                    mGestures.add(mCurrentGesture);
2383380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                }
2393380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                if (DEBUG) {
2403380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                    Slog.v(TAG, String.format("Wrote %d complete gestures to %s", mLastSaveLen, mLogfile));
2413380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                }
2423380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            } catch (IOException e) {
2433380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                Slog.e(TAG, String.format("Couldn't write gestures to %s", mLogfile), e);
2443380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler                mLastSaveLen = -1;
2453380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            }
2463380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
2473380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
2483380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler
2493380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2503380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        save();
2513380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        if (mLastSaveLen >= 0) {
2523380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            pw.println(String.valueOf(mLastSaveLen) + " gestures written to " + mLogfile);
2533380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        } else {
2543380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler            pw.println("error writing gestures");
2553380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler        }
2563380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler    }
2573380534a62abf20b4509db6068ac02b1b880712fDaniel Sandler}
258