Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e961188e authored by Kurt Partridge's avatar Kurt Partridge
Browse files

only output every kth word to log

multi-project CL with Ib5b544b9b2d8b0e4419238976b2e274e5ac564f8

Bug: 6188932
Change-Id: Iea68cf36924d6fda126130a98431a6ce02ba251e
parent 01106f6a
Loading
Loading
Loading
Loading
+58 −8
Original line number Original line Diff line number Diff line
@@ -197,6 +197,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
        Log.d(TAG, "stop called");
        Log.d(TAG, "stop called");
        if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) {
        if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) {
            mLoggingState = LOGGING_STATE_STOPPING;
            mLoggingState = LOGGING_STATE_STOPPING;
            flushEventQueue(true);
            // put this in the Handler queue so pending writes are processed first.
            // put this in the Handler queue so pending writes are processed first.
            mLoggingHandler.post(new Runnable() {
            mLoggingHandler.post(new Runnable() {
                @Override
                @Override
@@ -379,11 +380,52 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
        mCurrentLogUnit.addLogAtom(keys, values, false);
        mCurrentLogUnit.addLogAtom(keys, values, false);
    }
    }


    // Used to track how often words are logged.  Too-frequent logging can leak
    // semantics, disclosing private data.
    /* package for test */ static class LoggingFrequencyState {
        private static final int DEFAULT_WORD_LOG_FREQUENCY = 10;
        private int mWordsRemainingToSkip;
        private final int mFrequency;

        /**
         * Tracks how often words may be uploaded.
         *
         * @param frequency 1=Every word, 2=Every other word, etc.
         */
        public LoggingFrequencyState(int frequency) {
            mFrequency = frequency;
            mWordsRemainingToSkip = mFrequency;
        }

        public void onWordLogged() {
            mWordsRemainingToSkip = mFrequency;
        }

        public void onWordNotLogged() {
            if (mWordsRemainingToSkip > 1) {
                mWordsRemainingToSkip--;
            }
        }

        public boolean isSafeToLog() {
            return mWordsRemainingToSkip <= 1;
        }
    }

    /* package for test */ LoggingFrequencyState mLoggingFrequencyState =
            new LoggingFrequencyState(LoggingFrequencyState.DEFAULT_WORD_LOG_FREQUENCY);

    /* package for test */ boolean isPrivacyThreat(String word) {
    /* package for test */ boolean isPrivacyThreat(String word) {
        // currently: word not in dictionary or contains numbers.
        // Current checks:
        // - Word not in dictionary
        // - Word contains numbers
        // - Privacy-safe word not logged recently
        if (TextUtils.isEmpty(word)) {
        if (TextUtils.isEmpty(word)) {
            return false;
            return false;
        }
        }
        if (!mLoggingFrequencyState.isSafeToLog()) {
            return true;
        }
        final int length = word.length();
        final int length = word.length();
        boolean hasLetter = false;
        boolean hasLetter = false;
        for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
        for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
@@ -410,15 +452,26 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
        return false;
        return false;
    }
    }


    private void onWordComplete(String word) {
        final boolean isPrivacyThreat = isPrivacyThreat(word);
        flushEventQueue(isPrivacyThreat);
        if (isPrivacyThreat) {
            mLoggingFrequencyState.onWordNotLogged();
        } else {
            mLoggingFrequencyState.onWordLogged();
        }
    }

    /**
    /**
     * Write out enqueued LogEvents to the log, possibly dropping privacy sensitive events.
     * Write out enqueued LogEvents to the log, possibly dropping privacy sensitive events.
     */
     */
    /* package for test */ synchronized void flushQueue(boolean removePotentiallyPrivateEvents) {
    /* package for test */ synchronized void flushEventQueue(
            boolean removePotentiallyPrivateEvents) {
        if (isAllowedToLog()) {
        if (isAllowedToLog()) {
            mCurrentLogUnit.setRemovePotentiallyPrivateEvents(removePotentiallyPrivateEvents);
            mCurrentLogUnit.setRemovePotentiallyPrivateEvents(removePotentiallyPrivateEvents);
            mLoggingHandler.post(mCurrentLogUnit);
            mLoggingHandler.post(mCurrentLogUnit);
            mCurrentLogUnit = new LogUnit();
        }
        }
        mCurrentLogUnit = new LogUnit();
    }
    }


    private synchronized void outputEvent(final String[] keys, final Object[] values) {
    private synchronized void outputEvent(final String[] keys, final Object[] values) {
@@ -652,7 +705,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
        final ResearchLogger researchLogger = getInstance();
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueuePotentiallyPrivateEvent(
        researchLogger.enqueuePotentiallyPrivateEvent(
                EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values);
                EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values);
        researchLogger.flushQueue(researchLogger.isPrivacyThreat(autoCorrection));
    }
    }


    private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = {
    private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = {
@@ -665,7 +717,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
        };
        };
        final ResearchLogger researchLogger = getInstance();
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_COMMITTEXT, values);
        researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_COMMITTEXT, values);
        researchLogger.flushQueue(researchLogger.isPrivacyThreat(scrubbedWord));
        researchLogger.onWordComplete(scrubbedWord);
    }
    }


    private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = {
    private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = {
@@ -743,7 +795,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
            }
            }
            final ResearchLogger researchLogger = getInstance();
            final ResearchLogger researchLogger = getInstance();
            researchLogger.enqueueEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values);
            researchLogger.enqueueEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values);
            researchLogger.flushQueue(true); // Play it safe.  Remove privacy-sensitive events.
            researchLogger.flushEventQueue(true); // Play it safe.  Remove privacy-sensitive events.
        }
        }
    }
    }


@@ -824,7 +876,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
        final ResearchLogger researchLogger = getInstance();
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueuePotentiallyPrivateEvent(
        researchLogger.enqueuePotentiallyPrivateEvent(
                EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values);
                EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values);
        researchLogger.flushQueue(researchLogger.isPrivacyThreat(cs.toString()));
    }
    }


    private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = {
    private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = {
@@ -839,7 +890,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
        final ResearchLogger researchLogger = getInstance();
        final ResearchLogger researchLogger = getInstance();
        researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY,
        researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY,
                values);
                values);
        researchLogger.flushQueue(researchLogger.isPrivacyThreat(suggestion.toString()));
    }
    }


    private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = {
    private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = {