added profiling

This commit is contained in:
Mariotaku Lee 2015-03-04 16:02:32 +08:00
parent e11e9cb1d4
commit c02fda3e4f
20 changed files with 772 additions and 5 deletions

@ -1 +1 @@
Subproject commit cf66bea00da85aa4c65e62b79918e3e6909e9327
Subproject commit 524ca7a432be4c55be3841813fe7326f2fbf08c1

View File

@ -223,7 +223,11 @@ public interface SharedPreferenceConstants {
@Preference(type = BOOLEAN, exportable = false)
public static final String KEY_UCD_DATA_PROFILING = "ucd_data_profiling";
@Preference(type = BOOLEAN, exportable = false)
public static final String KEY_SPICE_DATA_PROFILING = "spice_data_profiling";
@Preference(type = BOOLEAN, exportable = false)
public static final String KEY_SHOW_UCD_DATA_PROFILING_REQUEST = "show_ucd_data_profiling_request";
@Preference(type = BOOLEAN, exportable = false)
public static final String KEY_SHOW_SPICE_DATA_PROFILING_REQUEST = "show_spice_data_profiling_request";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
public static final String KEY_DISPLAY_SENSITIVE_CONTENTS = "display_sensitive_contents";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = true)

View File

@ -0,0 +1,88 @@
package edu.tsinghua.spice;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationManager;
import android.os.IBinder;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
/**
* Created by Denny C. Ng on 2/20/15.
*
* Request location ONCE per WAKE_PERIOD_IN_MILLI.
*/
public class SpiceService extends Service {
public static final long LOCATION_PERIOD_IN_MILLI = 15 * 60 * 1000;
public static final String ACTION_GET_LOCATION = "edu.tsinghua.spice.GET_LOCATION";
private LocationManager mLocationManager;
private AlarmManager mAlarmManager;
private LocationUpdateReceiver mAlarmReceiver;
private PendingIntent locationIntent;
private PendingIntent uploadIntent;
@Override
public IBinder onBind(final Intent intent) {
throw new IllegalStateException("Not implemented.");
}
@Override
public void onCreate() {
super.onCreate();
SpiceProfilingUtil.log(this, "onCreate");
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mAlarmManager = (AlarmManager) getSystemService(Service.ALARM_SERVICE);
mAlarmReceiver = new LocationUpdateReceiver();
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_GET_LOCATION);
registerReceiver(mAlarmReceiver, filter);
final Intent intent = new Intent(ACTION_GET_LOCATION);
locationIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), LOCATION_PERIOD_IN_MILLI,
locationIntent);
// Upload Service
final Intent i = new Intent(SpiceUploadReceiver.ACTION_UPLOAD_PROFILE);
uploadIntent = PendingIntent.getBroadcast(this, 0, i, 0);
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 12 * 60 * 60 * 1000,
uploadIntent);
}
@Override
public void onDestroy() {
mAlarmManager.cancel(locationIntent);
unregisterReceiver(mAlarmReceiver);
super.onDestroy();
}
private final class LocationUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
if (mLocationManager == null) return;
SpiceProfilingUtil.log(context, "AlarmReceiver");
final String provider = LocationManager.NETWORK_PROVIDER;
if (mLocationManager.isProviderEnabled(provider)) {
final Location location = mLocationManager.getLastKnownLocation(provider);
if (location != null) {
SpiceProfilingUtil.profile(SpiceService.this, SpiceProfilingUtil.FILE_NAME_LOCATION, location.getTime() + ","
+ location.getLatitude() + "," + location.getLongitude() + "," + location.getProvider());
SpiceProfilingUtil.log(context,
location.getTime() + "," + location.getLatitude() + "," + location.getLongitude() + ","
+ location.getProvider());
}
}
}
}
}

View File

@ -0,0 +1,38 @@
package edu.tsinghua.spice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import org.mariotaku.twidere.util.Utils;
import edu.tsinghua.spice.Task.SpiceAsyUploadTask;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
/**
* Created by Denny C. Ng on 2/20/15.
*/
public class SpiceUploadReceiver extends BroadcastReceiver {
public static final String ACTION_UPLOAD_PROFILE = "edu.tsinghua.spice.UPLOAD_PROFILE";
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
final boolean isWifi = Utils.isOnWifi(context.getApplicationContext());
final boolean isCharging = SpiceProfilingUtil.isCharging(context.getApplicationContext());
if (WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION.equals(action)) {
final boolean wifi = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false);
SpiceProfilingUtil.profile(context, SpiceProfilingUtil.FILE_NAME_WIFI, wifi ? "connected" : "disconnected");
SpiceProfilingUtil.log(context, wifi ? "connected" : "disconnected" );
}
if (isWifi && isCharging) {
new SpiceAsyUploadTask(context).execute();
}
}
}

View File

@ -0,0 +1,144 @@
package edu.tsinghua.spice.Task;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.provider.Settings;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import edu.tsinghua.spice.Utilies.SpiceHttpUtil;
import edu.tsinghua.spice.Utilies.SpiceIOUtil;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
import static org.mariotaku.twidere.util.Utils.copyStream;
/**
* Created by Denny C. Ng on 2/20/15.
*/
public class SpiceAsyUploadTask extends AsyncTask<Void, Void, Void> {
private static final String PROFILE_SERVER_URL = "http://166.111.139.60:18080/boss/faces/test/U001";
private static final String LAST_UPLOAD_DATE = "last_upload_time";
private static final double MILLSECS_HALF_DAY = 1000 * 60 * 60 * 12;
//private final String device_id;
private final Context context;
private SpiceHttpUtil uploadClient;
public SpiceAsyUploadTask(final Context context) {
this.context = context;
// device_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
public void uploadMultipart(SpiceHttpUtil client, final File file) {
String fileName = file.getName();
final String app_root = file.getParent();
final File tmp_dir = new File(app_root + "/spice");
if (!tmp_dir.exists()) {
if (!tmp_dir.mkdirs()) {
SpiceProfilingUtil.log(context, "cannot create folder spice, do nothing.");
return;
}
}
final File tmp = new File(tmp_dir, file.getName());
file.renameTo(tmp);
try {
client.connectForMultipart();
client.addFilePart("file",fileName, SpiceIOUtil.readFile(tmp));
client.finishMultipart();
String serverResponseCode = client.getResponse();
if (serverResponseCode.indexOf("00") > -1) {
SpiceProfilingUtil.log(context, "server has already received file " + tmp.getName());
tmp.delete();
} else {
SpiceProfilingUtil.log(context, "server does not receive file " + tmp.getName());
putBackProfile(context, tmp, file);
}
} catch (Exception e) {
e.printStackTrace();
putBackProfile(context, tmp, file);
}
}
@Override
protected Void doInBackground(final Void... params) {
final SharedPreferences prefs = context.getSharedPreferences("spice_data_profiling", Context.MODE_PRIVATE);
if (prefs.contains(LAST_UPLOAD_DATE)) {
final long lastUpload = prefs.getLong(LAST_UPLOAD_DATE, System.currentTimeMillis());
final double deltaDays = (System.currentTimeMillis() - lastUpload) / (MILLSECS_HALF_DAY * 2);
if (deltaDays < 1) {
SpiceProfilingUtil.log(context, "Last uploaded was conducted in 1 day ago.");
return null;
}
}
final File root = context.getFilesDir();
final File[] spiceFiles = root.listFiles(new SpiceFileFilter());
uploadToServer(spiceFiles);
prefs.edit().putLong(LAST_UPLOAD_DATE, System.currentTimeMillis()).commit();
return null;
}
private boolean uploadToServer(final File... files) {
for (final File file : files) {
if (file.isDirectory()) {
continue;
}
final String url = PROFILE_SERVER_URL;
SpiceProfilingUtil.log(context, url);
uploadClient = new SpiceHttpUtil(url);
uploadMultipart(uploadClient, file);
}
return false;
}
public static void putBackProfile(final Context context, final File tmp, final File profile) {
boolean success;
if (profile.exists()) {
try {
final FileOutputStream os = new FileOutputStream(tmp, true);
final FileInputStream is = new FileInputStream(profile);
copyStream(is, os);
is.close();
os.close();
} catch (final IOException e) {
e.printStackTrace();
success = false;
}
success = true;
if (success && tmp.renameTo(profile) && tmp.delete()) {
SpiceProfilingUtil.log(context, "put profile back success");
} else {
SpiceProfilingUtil.log(context, "put profile back failed");
}
} else {
if (tmp.renameTo(profile)) {
SpiceProfilingUtil.log(context, "put profile back success");
} else {
SpiceProfilingUtil.log(context, "put profile back failed");
}
}
}
}

View File

@ -0,0 +1,23 @@
package edu.tsinghua.spice.Task;
import java.io.File;
import java.io.FileFilter;
/**
* Created by Denny C. Ng on 2/21/15.
*/
public final class SpiceFileFilter implements FileFilter {
@Override
public boolean accept(final File file) {
return file.isFile() && "spi".equalsIgnoreCase(getExtension(file));
}
static String getExtension(final File file) {
final String name = file.getName();
final int pos = name.lastIndexOf('.');
if (pos == -1) return null;
return name.substring(pos + 1);
}
}

View File

@ -0,0 +1,75 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.tsinghua.spice.Utilies;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
/**
* Created by Denny C. Ng on 2/28/15.
*/
public class NetworkStateUtil {
private static int getConnectedTypeValue(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
return mNetworkInfo.getType();
}
}
return -1;
}
public static String getConnectedType (Context context) {
int type = -1;
type = getConnectedTypeValue(context);
String network = "unknown";
switch (type) {
case 0:
network = "cellular";
break;
case 1:
network = "wifi";
break;
case 2:
network = "wimax";
break;
case 3:
network = "ethernet";
break;
case 4:
network = "bluetooth";
break;
case -1:
network = "ERROR";
break;
default:
network = "unknown";
break;
}
return network;
}
}

View File

@ -0,0 +1,90 @@
package edu.tsinghua.spice.Utilies;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Created by Denny C. Ng on 2/20/15.
* Copyright (C) 2013 Surviving with Android (http://www.survivingwithandroid.com)
*
* 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.
*/
public class SpiceHttpUtil {
private String url;
private HttpURLConnection con;
private OutputStream os;
private String delimiter = "--";
private String boundary = "SwA"+Long.toString(System.currentTimeMillis())+"SwA";
public SpiceHttpUtil(String url) {
this.url = url;
}
public void connectForMultipart() throws Exception {
con = (HttpURLConnection) ( new URL(url)).openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
con.connect();
os = con.getOutputStream();
}
public void addFormPart(String paramName, String value) throws Exception {
writeParamData(paramName, value);
}
public void addFilePart(String paramName, String fileName, byte[] data) throws Exception {
os.write( (delimiter + boundary + "\r\n").getBytes());
os.write( ("Content-Disposition: form-data; name=\"" + paramName + "\"; filename=\"" + fileName + "\"\r\n" ).getBytes());
os.write( ("Content-Type: application/octet-stream\r\n" ).getBytes());
os.write( ("Content-Transfer-Encoding: binary\r\n" ).getBytes());
os.write("\r\n".getBytes());
os.write(data);
os.write("\r\n".getBytes());
}
public void finishMultipart() throws Exception {
os.write( (delimiter + boundary + delimiter + "\r\n").getBytes());
}
public String getResponse() throws Exception {
InputStream is = con.getInputStream();
byte[] b1 = new byte[1024];
StringBuffer buffer = new StringBuffer();
while ( is.read(b1) != -1)
buffer.append(new String(b1));
con.disconnect();
return buffer.toString();
}
private void writeParamData(String paramName, String value) throws Exception {
os.write( (delimiter + boundary + "\r\n").getBytes());
os.write( "Content-Type: text/plain\r\n".getBytes());
os.write( ("Content-Disposition: form-data; name=\"" + paramName + "\"\r\n").getBytes());;
os.write( ("\r\n" + value + "\r\n").getBytes());
}
}

View File

@ -0,0 +1,33 @@
package edu.tsinghua.spice.Utilies;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Created by Denny C. Ng on 2/20/15.
*/
public class SpiceIOUtil {
public static byte[] readFile(String file) throws IOException {
return readFile(new File(file));
}
public static byte[] readFile(File file) throws IOException {
// Open file
RandomAccessFile f = new RandomAccessFile(file, "r");
try {
// Get and check length
long longlength = f.length();
int length = (int) longlength;
if (length != longlength)
throw new IOException("File size >= 2 GB");
// Read file and return data
byte[] data = new byte[length];
f.readFully(data);
return data;
} finally {
f.close();
}
}
}

View File

@ -0,0 +1,83 @@
package edu.tsinghua.spice.Utilies;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.BatteryManager;
import android.os.Build;
import android.util.Log;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.util.Utils;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
/**
* Created by Denny C. Ng on 2/20/15.
*/
public class SpiceProfilingUtil {
public static final String FILE_NAME_PROFILE = "Profile_SPICE";
public static final String FILE_NAME_LOCATION = "Location_SPICE";
public static final String FILE_NAME_APP = "App_SPICE";
public static final String FILE_NAME_WIFI = "Wifi_SPICE";
public static final String FILE_NAME_ONWIFI = "onWifi_SPICE";
public static final String FILE_NAME_ONLAUNCH = "onLaunch_SPICE";
public static boolean isCharging(final Context context) {
if (context == null) return false;
final Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
if (intent == null) return false;
final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB;
}
public static boolean log(final Context context, final String msg) {
if (Utils.isDebuggable(context)) {
final StackTraceElement ste = new Throwable().fillInStackTrace().getStackTrace()[1];
final String fullname = ste.getClassName();
final String name = fullname.substring(fullname.lastIndexOf('.'));
final String tag = name + "." + ste.getMethodName();
Log.d(tag, msg);
return true;
} else
return false;
}
public static void profile(final Context context, final long account_id, final String text) {
profile(context, account_id + "_" + FILE_NAME_PROFILE, text);
}
public static void profile(final Context context, final String name, final String text) {
if (context == null) return;
final SharedPreferences prefs = context.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME,
Context.MODE_PRIVATE);
if (!prefs.getBoolean(Constants.KEY_SPICE_DATA_PROFILING, false)) return;
String uuid = "XXX";
if (Build.SERIAL.length() > 0)
uuid = Build.SERIAL;
final String filename = uuid + "_" + name + ".spi";
new Thread() {
@Override
public void run() {
try {
final FileOutputStream fos = context.openFileOutput(filename, Context.MODE_APPEND);
if (fos == null) return;
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write(text + "," + System.currentTimeMillis() + "\n");
bw.flush();
fos.close();
} catch (final Exception e) {
e.printStackTrace();
}
}
;
}.start();
}
}

View File

@ -0,0 +1,76 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.tsinghua.spice.Utilies;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.util.TwidereLinkify;
/**
* Created by Denny C. Ng on 2/26/15.
*/
public class TypeMapingUtil {
public static String getLinkType (int type) {
String linkType = "";
switch (type) {
case TwidereLinkify.LINK_TYPE_MENTION:
linkType = "mention";
break;
case TwidereLinkify.LINK_TYPE_CASHTAG:
linkType = "cashTag";
break;
case TwidereLinkify.LINK_TYPE_LINK:
linkType = "urlLink";
break;
case TwidereLinkify.LINK_TYPE_LIST:
linkType = "userList";
break;
case TwidereLinkify.LINK_TYPE_STATUS:
linkType = "status";
break;
case TwidereLinkify.LINK_TYPE_USER_ID:
linkType = "userID";
break;
case TwidereLinkify.LINK_TYPE_HASHTAG:
linkType = "hashTag";
break;
default:
linkType = "unknown";
break;
}
return linkType;
}
public static String getMediaType (int type) {
String mediaType = "";
switch (type) {
case ParcelableMedia.TYPE_IMAGE:
mediaType = "image";
break;
default:
mediaType = "unknown";
break;
}
return mediaType;
}
}

View File

@ -106,6 +106,8 @@ import org.mariotaku.twidere.view.TabPagerIndicator;
import org.mariotaku.twidere.view.TintedStatusFrameLayout;
import org.mariotaku.twidere.view.iface.IHomeActionButton;
import edu.tsinghua.spice.Utilies.NetworkStateUtil;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
import edu.ucdavis.earlybird.ProfilingUtil;
import static org.mariotaku.twidere.util.CompareUtils.classEquals;
@ -356,6 +358,10 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
}
// UCD
ProfilingUtil.profile(this, ProfilingUtil.FILE_NAME_APP, "App onStart");
// spice
SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_APP, "App Launch" + "," + Build.MODEL);
SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_ONLAUNCH, "App Launch" + "," + NetworkStateUtil.getConnectedType(this) + "," + Build.MODEL);
//end
updateUnreadCount();
}
@ -371,6 +377,10 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
// UCD
ProfilingUtil.profile(this, ProfilingUtil.FILE_NAME_APP, "App onStop");
// spice
SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_APP, "App Stop");
SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_ONLAUNCH, "App Stop" + "," + NetworkStateUtil.getConnectedType(this) + "," + Build.MODEL);
//end
super.onStop();
}
@ -744,7 +754,8 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
}
private void showDataProfilingRequest() {
if (mPreferences.getBoolean(KEY_SHOW_UCD_DATA_PROFILING_REQUEST, true)) {
//spice
if (mPreferences.getBoolean(KEY_SHOW_UCD_DATA_PROFILING_REQUEST, true) || mPreferences.getBoolean(KEY_SHOW_SPICE_DATA_PROFILING_REQUEST, true)) {
final Intent intent = new Intent(this, DataProfilingSettingsActivity.class);
final PendingIntent content_intent = PendingIntent.getActivity(this, 0, intent, 0);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);

View File

@ -59,6 +59,7 @@ import org.mariotaku.twidere.util.net.TwidereHostAddressResolver;
import java.io.File;
import edu.tsinghua.spice.SpiceService;
import edu.ucdavis.earlybird.UCDService;
import twitter4j.http.HostAddressResolver;
@ -230,7 +231,14 @@ public class TwidereApplication extends MultiDexApplication implements Constants
} else if (KEY_UCD_DATA_PROFILING.equals(key)) {
stopService(new Intent(this, UCDService.class));
startProfilingServiceIfNeeded(this);
} else if (KEY_CONSUMER_KEY.equals(key) || KEY_CONSUMER_SECRET.equals(key) || KEY_API_URL_FORMAT.equals(key)
}
//spice
else if (KEY_SPICE_DATA_PROFILING.equals(key)) {
stopService(new Intent(this, SpiceService.class));
startProfilingServiceIfNeeded(this);
}
//end
else if (KEY_CONSUMER_KEY.equals(key) || KEY_CONSUMER_SECRET.equals(key) || KEY_API_URL_FORMAT.equals(key)
|| KEY_AUTH_TYPE.equals(key) || KEY_SAME_OAUTH_SIGNING_URL.equals(key)) {
final SharedPreferences.Editor editor = preferences.edit();
editor.putLong(KEY_API_LAST_CHANGE, System.currentTimeMillis());

View File

@ -56,6 +56,9 @@ public class DataProfilingSettingsFragment extends BaseFragment implements OnCli
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
if (mPreferences.contains(KEY_UCD_DATA_PROFILING)) {
mCheckBox.setChecked(mPreferences.getBoolean(KEY_UCD_DATA_PROFILING, false));
//spice
mCheckBox.setChecked(mPreferences.getBoolean(KEY_SPICE_DATA_PROFILING, false));
//end
}
mSaveButton.setOnClickListener(this);
mPreviewButton.setOnClickListener(this);
@ -68,6 +71,10 @@ public class DataProfilingSettingsFragment extends BaseFragment implements OnCli
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putBoolean(KEY_UCD_DATA_PROFILING, mCheckBox.isChecked());
editor.putBoolean(KEY_SHOW_UCD_DATA_PROFILING_REQUEST, false);
//spice
editor.putBoolean(KEY_SPICE_DATA_PROFILING, mCheckBox.isChecked());
editor.putBoolean(KEY_SHOW_SPICE_DATA_PROFILING_REQUEST, false);
//end
editor.commit();
getActivity().onBackPressed();
break;

View File

@ -39,6 +39,8 @@ import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
import org.mariotaku.twidere.view.holder.GapViewHolder;
import org.mariotaku.twidere.view.holder.StatusViewHolder;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
import static org.mariotaku.twidere.util.Utils.setMenuForStatus;
/**
@ -280,8 +282,16 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
if (twitter == null) return;
if (status.is_favorite) {
twitter.destroyFavoriteAsync(status.account_id, status.id);
//spice
SpiceProfilingUtil.profile(getActivity(), status.account_id, status.id + ",Unfavor," + status.account_id + "," + status.user_id + "," + status.timestamp);
SpiceProfilingUtil.log(getActivity(),status.id + ",Unfavor," + status.account_id + "," + status.user_id + "," + status.timestamp);
//end
} else {
twitter.createFavoriteAsync(status.account_id, status.id);
//spice
SpiceProfilingUtil.profile(getActivity(),status.account_id, status.id + ",Favor," + status.account_id + "," + status.user_id + "," + status.timestamp);
SpiceProfilingUtil.log(getActivity(),status.id + ",Favor," + status.account_id + "," + status.user_id + "," + status.timestamp);
//end
}
break;
}

View File

@ -107,9 +107,12 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
import edu.tsinghua.spice.Utilies.TypeMapingUtil;
import twitter4j.TwitterException;
import static android.text.TextUtils.isEmpty;
import static android.text.TextUtils.substring;
import static org.mariotaku.twidere.util.UserColorNameUtils.clearUserColor;
import static org.mariotaku.twidere.util.UserColorNameUtils.clearUserNickname;
import static org.mariotaku.twidere.util.UserColorNameUtils.getUserColor;
@ -154,9 +157,11 @@ public class StatusFragment extends BaseSupportFragment
final long statusId = args.getLong(EXTRA_STATUS_ID, -1);
final long maxId = args.getLong(EXTRA_MAX_ID, -1);
final long sinceId = args.getLong(EXTRA_SINCE_ID, -1);
final StatusRepliesLoader loader = new StatusRepliesLoader(getActivity(), accountId,
screenName, statusId, maxId, sinceId, null, null, 0, true);
loader.setComparator(ParcelableStatus.REVERSE_ID_COMPARATOR);
return loader;
}
@ -287,6 +292,12 @@ public class StatusFragment extends BaseSupportFragment
final ParcelableStatus status = mStatusAdapter.getStatus();
if (status == null) return;
Utils.openMediaDirectly(getActivity(), accountId, media, status.media);
//spice
SpiceProfilingUtil.log(getActivity(),
status.id + ",Clicked," + accountId + "," + status.user_id + "," + status.text_plain.length() + "," + media.media_url + "," + TypeMapingUtil.getMediaType(media.type) + "," + status.timestamp );
SpiceProfilingUtil.profile(getActivity(),accountId,
status.id + ",Clicked," + accountId + "," + status.user_id + "," + status.text_plain.length() + "," + media.media_url + "," + TypeMapingUtil.getMediaType(media.type) + "," + status.timestamp);
//end
}
@Override
@ -357,6 +368,19 @@ public class StatusFragment extends BaseSupportFragment
}
getLoaderManager().initLoader(LOADER_ID_STATUS_REPLIES, args, mRepliesLoaderCallback);
mRepliesLoaderInitialized = true;
//spice
if (status.media != null) {
SpiceProfilingUtil.profile(getActivity(), status.account_id,
status.id + ",Preview," + status.account_id + "," + status.user_id + "," + status.text_plain.length() + "," + TypeMapingUtil.getMediaType(status.media[0].type) + "," + status.timestamp );
SpiceProfilingUtil.log(getActivity(),
status.id + ",Preview," + status.account_id + "," + status.user_id + "," + status.text_plain.length() + "," + TypeMapingUtil.getMediaType(status.media[0].type) + "," + status.timestamp );
} else {
SpiceProfilingUtil.profile(getActivity(), status.account_id,
status.id + ",Words," + status.account_id + "," + status.user_id + "," + status.text_plain.length() + "," + status.timestamp );
SpiceProfilingUtil.log(getActivity(),status.account_id + ",Words," + status.user_id + "," + status.text_plain.length() + "," + status.timestamp );
}
//end
}
private void setConversation(List<ParcelableStatus> data) {
@ -954,8 +978,18 @@ public class StatusFragment extends BaseSupportFragment
case MENU_FAVORITE: {
if (status.is_favorite) {
twitter.destroyFavoriteAsync(status.account_id, status.id);
//spice
SpiceProfilingUtil.profile(adapter.getContext(),
status.account_id, status.id + ",Unfavor," + status.account_id + "," + status.user_id + "," + status.timestamp);
SpiceProfilingUtil.log(adapter.getContext(),status.id + ",Unfavor," + status.account_id + "," + status.user_id + "," + status.timestamp);
//end
} else {
twitter.createFavoriteAsync(status.account_id, status.id);
//spice
SpiceProfilingUtil.profile(adapter.getContext(),
status.account_id, status.id + ",Favor," + status.account_id + "," + status.user_id + "," + status.timestamp);
SpiceProfilingUtil.log(adapter.getContext(),status.id + ",Favor," + status.account_id + "," + status.user_id + "," + status.timestamp);
//end
}
break;
}

View File

@ -31,9 +31,12 @@ import android.util.Log;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.util.Utils;
import edu.tsinghua.spice.Utilies.NetworkStateUtil;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
public class ConnectivityStateReceiver extends BroadcastReceiver implements Constants {
private static final String RECEIVER_LOGTAG = LOGTAG + "." + "Connectivity";
private static final String RECEIVER_LOGTAG = LOGTAG + "." + "ConnectivityStateReceiver";
@Override
public void onReceive(final Context context, final Intent intent) {
@ -43,5 +46,7 @@ public class ConnectivityStateReceiver extends BroadcastReceiver implements Cons
if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) return;
startProfilingServiceIfNeeded(context);
startRefreshServiceIfNeeded(context);
//spice
SpiceProfilingUtil.profile(context,SpiceProfilingUtil.FILE_NAME_ONWIFI, NetworkStateUtil.getConnectedType(context));
}
}

View File

@ -51,6 +51,7 @@ import org.mariotaku.twidere.model.MediaUploadResult;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableDirectMessage;
import org.mariotaku.twidere.model.ParcelableLocation;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableMediaUpdate;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
@ -82,6 +83,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
import edu.tsinghua.spice.Utilies.TypeMapingUtil;
import twitter4j.MediaUploadResponse;
import twitter4j.Status;
import twitter4j.StatusUpdate;
@ -187,6 +190,7 @@ public class BackgroundOperationService extends IntentService implements Constan
protected void onHandleIntent(final Intent intent) {
if (intent == null) return;
final String action = intent.getAction();
switch (action) {
case INTENT_ACTION_UPDATE_STATUS:
handleUpdateStatusIntent(intent);
@ -257,6 +261,7 @@ public class BackgroundOperationService extends IntentService implements Constan
startForeground(NOTIFICATION_ID_SEND_DIRECT_MESSAGE, notification);
final SingleResponse<ParcelableDirectMessage> result = sendDirectMessage(builder, accountId, recipientId, text,
imageUri);
if (result.getData() != null && result.getData().id > 0) {
final ContentValues values = ContentValuesCreator.createDirectMessage(result.getData());
final String delete_where = DirectMessages.ACCOUNT_ID + " = " + accountId + " AND "
@ -264,6 +269,8 @@ public class BackgroundOperationService extends IntentService implements Constan
mResolver.delete(DirectMessages.Outbox.CONTENT_URI, delete_where, null);
mResolver.insert(DirectMessages.Outbox.CONTENT_URI, values);
showOkMessage(R.string.direct_message_sent, false);
} else {
final ContentValues values = createMessageDraft(accountId, recipientId, text, imageUri);
mResolver.insert(Drafts.CONTENT_URI, values);
@ -297,6 +304,7 @@ public class BackgroundOperationService extends IntentService implements Constan
final Uri draftUri = mResolver.insert(Drafts.CONTENT_URI, draftValues);
final long draftId = ParseUtils.parseLong(draftUri.getLastPathSegment(), -1);
mTwitter.addSendingDraftId(draftId);
try {
Thread.sleep(15000L);
} catch (InterruptedException e) {
@ -305,11 +313,13 @@ public class BackgroundOperationService extends IntentService implements Constan
final List<SingleResponse<ParcelableStatus>> result = updateStatus(builder, item);
boolean failed = false;
Exception exception = null;
final Expression where = Expression.equals(Drafts._ID, draftId);
final List<Long> failedAccountIds = ListUtils.fromArray(ParcelableAccount.getAccountIds(item.accounts));
for (final SingleResponse<ParcelableStatus> response : result) {
if (response.getData() == null) {
failed = true;
if (exception == null) {
@ -317,8 +327,23 @@ public class BackgroundOperationService extends IntentService implements Constan
}
} else if (response.getData().account_id > 0) {
failedAccountIds.remove(response.getData().account_id);
//spice
if (response.getData().media == null) {
SpiceProfilingUtil.log(this.getBaseContext(), response.getData().id + ",Tweet," + response.getData().account_id + ","
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id);
SpiceProfilingUtil.profile(this.getBaseContext(), response.getData().account_id, response.getData().id + ",Tweet," + response.getData().account_id + ","
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id);
} else
for (final ParcelableMedia spiceMedia : response.getData().media) {
SpiceProfilingUtil.log(this.getBaseContext(), response.getData().id + ",Media," + response.getData().account_id + ","
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id + "," + spiceMedia.media_url + "," + TypeMapingUtil.getMediaType(spiceMedia.type));
SpiceProfilingUtil.profile(this.getBaseContext(), response.getData().account_id, response.getData().id + ",Media," + response.getData().account_id + ","
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id + "," + spiceMedia.media_url + "," + TypeMapingUtil.getMediaType(spiceMedia.type));
}
//end
}
}
if (result.isEmpty()) {
showErrorMessage(R.string.action_updating_status, getString(R.string.no_account_selected), false);
} else if (failed) {
@ -392,6 +417,10 @@ public class BackgroundOperationService extends IntentService implements Constan
true);
}
Utils.setLastSeen(this, recipientId, System.currentTimeMillis());
return SingleResponse.getInstance(directMessage);
} catch (final IOException e) {
return SingleResponse.getInstance(e);

View File

@ -79,6 +79,7 @@ import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
import edu.ucdavis.earlybird.ProfilingUtil;
import twitter4j.DirectMessage;
import twitter4j.Paging;
@ -2394,6 +2395,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
// UCD
ProfilingUtil.profile(mContext, accountId,
"Download tweets, " + TwidereArrayUtils.toString(statusIds, ',', true));
//spice
SpiceProfilingUtil.profile(mContext, accountId, accountId + ",Refresh," + TwidereArrayUtils.toString(statusIds, ',', true));
//end
all_statuses.addAll(Arrays.asList(values));
// Insert previously fetched items.
final Uri insertUri = appendQueryParameters(uri, new NameValuePairImpl(QUERY_PARAM_NOTIFY, notify));

View File

@ -28,6 +28,8 @@ import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.util.TwidereLinkify.OnLinkClickListener;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
import edu.tsinghua.spice.Utilies.TypeMapingUtil;
import edu.ucdavis.earlybird.ProfilingUtil;
import static org.mariotaku.twidere.util.Utils.openStatus;
@ -51,6 +53,9 @@ public class OnLinkClickHandler implements OnLinkClickListener, Constants {
if (context == null || (manager != null && manager.isActive())) return;
// UCD
ProfilingUtil.profile(context, account_id, "Click, " + link + ", " + type);
//spice
SpiceProfilingUtil.profile(context, account_id, account_id + ",Visit," + link + "," + TypeMapingUtil.getLinkType(type));
//end
switch (type) {
case TwidereLinkify.LINK_TYPE_MENTION: {