ResearchLog splash screen

Bug: 6188932
Change-Id: I1b247ecc26a2dd4f3f1c1b1cd3d928af717ebdd5
main
Kurt Partridge 2012-07-18 18:41:15 -07:00
parent 3c233bf1a5
commit 4331012a9e
4 changed files with 194 additions and 7 deletions

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/research_splash_screen_layout">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.android.internal.widget.DialogTitle
style="?android:attr/windowTitleStyle"
android:singleLine="true"
android:ellipsize="end"
android:layout_width="match_parent"
android:layout_height="64dip"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:gravity="center_vertical|left"
android:text="@string/research_splash_title" />
<View android:layout_width="match_parent"
android:layout_height="2dip"
android:background="@android:color/holo_blue_light" />
</LinearLayout>
<TextView
android:text="@string/research_splash_content"
android:layout_height="fill_parent"
android:layout_width="match_parent"
android:layout_gravity="fill_horizontal|center_vertical"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:layout_marginBottom="16dip"
android:layout_marginTop="16dip"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:divider="?android:attr/dividerHorizontal"
android:showDividers="beginning"
android:dividerPadding="0dip">
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:measureWithLargestChild="true">
<Button
android:layout_width="0dip"
android:layout_gravity="left"
android:layout_weight="1"
android:maxLines="2"
stype="?android:attr/buttonBarButtonStyle"
android:textSize="14sp"
android:text="@string/research_dont_send_usage_info"
android:layout_height="wrap_content"
android:id="@+id/research_do_not_log_button" />
<Button
android:layout_width="0dip"
android:layout_gravity="right"
android:layout_weight="1"
android:maxLines="2"
style="?android:attr/buttonBarButtonStyle"
android:textSize="14sp"
android:text="@string/research_send_usage_info"
android:layout_height="wrap_content"
android:id="@+id/research_do_log_button" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -263,6 +263,19 @@
<!-- TODO: remove translatable=false attribute once text is stable -->
<string name="research_please_exit_feedback_form" translatable="false">Please exit the feedback dialog to access the research log menu</string>
<!-- Title of dialog shown at start informing users about contributing research usage data-->
<!-- TODO: remove translatable=false attribute once text is stable -->
<string name="research_splash_title" translatable="false">Usage Participation</string>
<!-- Contents of note explaining what data is collected and how. -->
<!-- TODO: remove translatable=false attribute once text is stable -->
<string name="research_splash_content" translatable="false">Thank you for dogfooding this keyboard.\n\nIf you like it, please help us make it better by sending us usage information. When enabled, the keyboard uploads general statistics, such as how fast you type, and also occasional samples of how you type words.\n\nNo passwords or non-dictionary words are ever automatically uploaded, and words are sampled infrequently enough so that reconstructing the meaning of what you typed is highly unlikely.\n\nYou can disable and reenable logging through the RLog menu by long-pressing on the microphone or settings key.\n</string>
<!-- Button label text for opting out of research usage data collection [CHAR LIMIT=50] -->
<!-- TODO: remove translatable=false attribute once text is stable -->
<string name="research_dont_send_usage_info" translatable="false">Do not send\nusage info</string>
<!-- Button label text for opting into research usage data collection [CHAR LIMIT=50] -->
<!-- TODO: remove translatable=false attribute once text is stable -->
<string name="research_send_usage_info" translatable="false">Send usage info</string>
<!-- Preference for input language selection -->
<string name="select_language">Input languages</string>

View File

@ -508,6 +508,17 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
return mKeyDetector.isProximityCorrectionEnabled();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
// Notify the research logger that the keyboard view has been attached. This is needed
// to properly show the splash screen, which requires that the window token of the
// KeyboardView be non-null.
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.getInstance().latinKeyboardView_onAttachedToWindow();
}
}
@Override
public void cancelAllMessages() {
mKeyTimerHandler.cancelAllMessages();

View File

@ -19,27 +19,36 @@ package com.android.inputmethod.research;
import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.inputmethodservice.InputMethodService;
import android.os.Build;
import android.os.IBinder;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.Button;
import android.widget.Toast;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.LatinKeyboardView;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.R;
@ -73,6 +82,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
/* package */ static boolean sIsLogging = false;
private static final int OUTPUT_FORMAT_VERSION = 1;
private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
private static final String PREF_RESEARCH_HAS_SEEN_SPLASH = "pref_research_has_seen_splash";
/* package */ static final String FILENAME_PREFIX = "researchLog";
private static final String FILENAME_SUFFIX = ".txt";
private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
@ -118,7 +128,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private Suggest mSuggest;
private Dictionary mDictionary;
private KeyboardSwitcher mKeyboardSwitcher;
private Context mContext;
private InputMethodService mInputMethodService;
private ResearchLogUploader mResearchLogUploader;
@ -163,11 +173,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mResearchLogUploader = new ResearchLogUploader(ims, mFilesDir);
mResearchLogUploader.start();
mKeyboardSwitcher = keyboardSwitcher;
mContext = ims;
mInputMethodService = ims;
mPrefs = prefs;
// TODO: force user to decide at splash screen instead of defaulting to on.
setLoggingAllowed(true);
}
private void cleanupLoggingDir(final File dir, final long time) {
@ -179,6 +186,73 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
public void latinKeyboardView_onAttachedToWindow() {
maybeShowSplashScreen();
}
private boolean hasSeenSplash() {
return mPrefs.getBoolean(PREF_RESEARCH_HAS_SEEN_SPLASH, false);
}
private Dialog mSplashDialog = null;
private void maybeShowSplashScreen() {
if (hasSeenSplash()) {
return;
}
if (mSplashDialog != null && mSplashDialog.isShowing()) {
return;
}
final IBinder windowToken = mKeyboardSwitcher.getKeyboardView().getWindowToken();
if (windowToken == null) {
return;
}
mSplashDialog = new Dialog(mInputMethodService, android.R.style.Theme_Holo_Dialog);
mSplashDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mSplashDialog.setContentView(R.layout.research_splash);
mSplashDialog.setCancelable(true);
final Window w = mSplashDialog.getWindow();
final WindowManager.LayoutParams lp = w.getAttributes();
lp.token = windowToken;
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
w.setAttributes(lp);
w.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
mSplashDialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
mInputMethodService.requestHideSelf(0);
}
});
final Button doNotLogButton = (Button) mSplashDialog.findViewById(
R.id.research_do_not_log_button);
doNotLogButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onUserLoggingElection(false);
mSplashDialog.dismiss();
}
});
final Button doLogButton = (Button) mSplashDialog.findViewById(R.id.research_do_log_button);
doLogButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onUserLoggingElection(true);
mSplashDialog.dismiss();
}
});
mSplashDialog.show();
}
public void onUserLoggingElection(final boolean enableLogging) {
setLoggingAllowed(enableLogging);
if (mPrefs == null) {
return;
}
final Editor e = mPrefs.edit();
e.putBoolean(PREF_RESEARCH_HAS_SEEN_SPLASH, true);
e.apply();
}
private File createLogFile(File filesDir) {
final StringBuilder sb = new StringBuilder();
sb.append(FILENAME_PREFIX).append('-');
@ -189,6 +263,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
private void start() {
maybeShowSplashScreen();
updateSuspendedState();
requestIndicatorRedraw();
if (!isAllowedToLog()) {
@ -705,7 +780,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
researchLogger.start();
if (editorInfo != null) {
final Context context = researchLogger.mContext;
final Context context = researchLogger.mInputMethodService;
try {
final PackageInfo packageInfo;
packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),
@ -900,7 +975,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// Play it safe. Remove privacy-sensitive events.
researchLogger.publishLogUnit(researchLogger.mCurrentLogUnit, true);
researchLogger.mCurrentLogUnit = new LogUnit();
getInstance().restart();
getInstance().stop();
}
}