summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml25
-rw-r--r--res/drawable-hdpi/ic_cm_stats_notif.pngbin0 -> 3168 bytes
-rw-r--r--res/drawable-mdpi/ic_cm_stats_notif.pngbin0 -> 3013 bytes
-rw-r--r--res/drawable-xhdpi/ic_cm_stats_notif.pngbin0 -> 3233 bytes
-rw-r--r--res/values/strings.xml24
-rw-r--r--res/xml/anonymous_stats.xml35
-rw-r--r--res/xml/device_info_settings.xml8
-rw-r--r--res/xml/preview_data.xml53
-rw-r--r--src/com/android/settings/Settings.java1
-rw-r--r--src/com/android/settings/cmstats/AnonymousStats.java138
-rw-r--r--src/com/android/settings/cmstats/PreviewData.java76
-rw-r--r--src/com/android/settings/cmstats/ReportingService.java119
-rw-r--r--src/com/android/settings/cmstats/ReportingServiceManager.java93
-rw-r--r--src/com/android/settings/cmstats/Utilities.java94
14 files changed, 666 insertions, 0 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f2e51a1..02809f7 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -138,6 +138,14 @@
android:resource="@id/wifi_settings" />
</activity>
+ <activity android:name="Settings$AnonymousStatsActivity"
+ android:label="@string/anonymous_statistics_title"
+ android:configChanges="orientation|keyboardHidden|screenSize"
+ android:clearTaskOnLaunch="true">
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.cmstats.AnonymousStats" />
+ </activity>
+
<!-- Keep compatibility with old shortcuts. -->
<activity-alias android:name=".wifi.WifiSettings"
android:taskAffinity="com.android.settings"
@@ -957,6 +965,23 @@
<activity android:name="ChooseLockPatternTutorial" android:exported="false"/>
+ <!-- Anonymous Statistics -->
+ <receiver android:name=".cmstats.ReportingServiceManager"
+ android:enabled="true"
+ android:exported="false"
+ android:label="ReportingServiceManager">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+ </intent-filter>
+ </receiver>
+
+ <service android:label="ReportingService"
+ android:enabled="true"
+ android:exported="false"
+ android:name=".cmstats.ReportingService">
+ </service>
+
<!-- Runs in the phone process since it needs access to the Phone object -->
<activity android:name=".deviceinfo.Status"
android:label="@string/device_status_activity_title"
diff --git a/res/drawable-hdpi/ic_cm_stats_notif.png b/res/drawable-hdpi/ic_cm_stats_notif.png
new file mode 100644
index 0000000..66fa7c0
--- /dev/null
+++ b/res/drawable-hdpi/ic_cm_stats_notif.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_cm_stats_notif.png b/res/drawable-mdpi/ic_cm_stats_notif.png
new file mode 100644
index 0000000..9113877
--- /dev/null
+++ b/res/drawable-mdpi/ic_cm_stats_notif.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_cm_stats_notif.png b/res/drawable-xhdpi/ic_cm_stats_notif.png
new file mode 100644
index 0000000..715eb9a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_cm_stats_notif.png
Binary files differ
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5a61b3d..2be38c8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4421,5 +4421,29 @@
<string name="mem_info">Memory</string>
<!-- About phone screen, status item label -->
+ <!-- Anonymous Statistics #CM -->
+ <!-- About device screen, list item title. Takes the user to the screen about opting in or out of anonymous statistics. -->
+ <string name="anonymous_statistics_title">CyanogenMod statistics</string>
+ <string name="anonymous_statistics_summary">Help make CyanogenMod better by opting into anonymous statistics reporting</string>
+ <string name="anonymous_statistics_warning_title">About</string>
+ <string name="anonymous_statistics_warning">Opting into CyanogenMod Statistics will allow non-personal data to be submitted to the
+ developers of CyanogenMod to track unique installations across devices. The information submitted includes an unique identifier,
+ which does not compromise your privacy or personal data. The data is submitted during each boot.\n\nFor an example of the data that is submitted, tap on Preview Data.</string>
+ <string name="enable_reporting_title">Enable reporting</string>
+ <string name="preview_data_title">Preview data</string>
+ <string name="preview_data_summary">%s</string>
+ <string name="view_stats_title">View stats</string>
+ <string name="anonymous_learn_more">Learn more</string>
+
+ <!-- Anonymous Statistics - Notification -->
+ <string name="anonymous_notification_desc">Enable or Disable CyanogenMod Statistics</string>
+
+ <!-- Anonymous Statistics - Preview -->
+ <string name="preview_id_title">Unique ID</string>
+ <string name="preview_device_title">Device</string>
+ <string name="preview_version_title">Version</string>
+ <string name="preview_country_title">Country</string>
+ <string name="preview_carrier_title">Carrier</string>
+
<!-- **** CYANOGENMOD ADDITIONS END **** -->
</resources>
diff --git a/res/xml/anonymous_stats.xml b/res/xml/anonymous_stats.xml
new file mode 100644
index 0000000..6c4621e
--- /dev/null
+++ b/res/xml/anonymous_stats.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The CyanogenMod 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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/anonymous_statistics_title"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+
+ <CheckBoxPreference
+ android:key="pref_anonymous_opt_in"
+ android:defaultValue="true"
+ android:title="@string/enable_reporting_title" />
+
+ <PreferenceScreen
+ android:title="@string/preview_data_title"
+ android:fragment="com.android.settings.cmstats.PreviewData" />
+
+ <Preference
+ android:key="pref_view_stats"
+ android:title="@string/view_stats_title" />
+
+</PreferenceScreen>
diff --git a/res/xml/device_info_settings.xml b/res/xml/device_info_settings.xml
index 0666034..c4c3b53 100644
--- a/res/xml/device_info_settings.xml
+++ b/res/xml/device_info_settings.xml
@@ -41,6 +41,14 @@
android:targetClass="com.android.settings.deviceinfo.Status" />
</PreferenceScreen>
+ <!-- Anonymous statistics - (CMStats) -->
+ <PreferenceScreen
+ android:key="cmstats"
+ android:title="@string/anonymous_statistics_title"
+ android:summary="@string/anonymous_statistics_summary"
+ android:fragment="com.android.settings.cmstats.AnonymousStats" >
+ </PreferenceScreen>
+
<!-- Legal Information -->
<PreferenceScreen
android:key="container"
diff --git a/res/xml/preview_data.xml b/res/xml/preview_data.xml
new file mode 100644
index 0000000..966e501
--- /dev/null
+++ b/res/xml/preview_data.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The CyanogenMod 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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/preview_data_title"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+
+ <Preference
+ android:key="preview_id"
+ style="?android:preferenceInformationStyle"
+ android:title="@string/preview_id_title"
+ android:summary="%s" />
+
+ <Preference
+ android:key="preview_device"
+ style="?android:preferenceInformationStyle"
+ android:title="@string/preview_device_title"
+ android:summary="%s" />
+
+ <Preference
+ android:key="preview_version"
+ style="?android:preferenceInformationStyle"
+ android:title="@string/preview_version_title"
+ android:summary="%s" />
+
+ <Preference
+ android:key="preview_country"
+ style="?android:preferenceInformationStyle"
+ android:title="@string/preview_country_title"
+ android:summary="%s" />
+
+ <Preference
+ android:key="preview_carrier"
+ style="?android:preferenceInformationStyle"
+ android:title="@string/preview_carrier_title"
+ android:summary="%s" />
+
+</PreferenceScreen>
+
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index f045db0..fbb6e15 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -833,4 +833,5 @@ public class Settings extends PreferenceActivity
public static class TextToSpeechSettingsActivity extends Settings { /* empty */ }
public static class AndroidBeamSettingsActivity extends Settings { /* empty */ }
public static class WifiDisplaySettingsActivity extends Settings { /* empty */ }
+ public static class AnonymousStatsActivity extends Settings { /* empty */ }
}
diff --git a/src/com/android/settings/cmstats/AnonymousStats.java b/src/com/android/settings/cmstats/AnonymousStats.java
new file mode 100644
index 0000000..f156a6f
--- /dev/null
+++ b/src/com/android/settings/cmstats/AnonymousStats.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod 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.
+ */
+
+package com.android.settings.cmstats;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+public class AnonymousStats extends SettingsPreferenceFragment
+ implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
+ Preference.OnPreferenceChangeListener {
+
+ private static final String VIEW_STATS = "pref_view_stats";
+
+ protected static final String ANONYMOUS_OPT_IN = "pref_anonymous_opt_in";
+
+ protected static final String ANONYMOUS_FIRST_BOOT = "pref_anonymous_first_boot";
+
+ protected static final String ANONYMOUS_LAST_CHECKED = "pref_anonymous_checked_in";
+
+ protected static final String ANONYMOUS_ALARM_SET = "pref_anonymous_alarm_set";
+
+ private CheckBoxPreference mEnableReporting;
+
+ private Preference mViewStats;
+
+ private Dialog mOkDialog;
+
+ private boolean mOkClicked;
+
+ private SharedPreferences mPrefs;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getPreferenceManager() != null) {
+ addPreferencesFromResource(R.xml.anonymous_stats);
+ PreferenceScreen prefSet = getPreferenceScreen();
+ mPrefs = getActivity().getSharedPreferences("CMStats", 0);
+ mEnableReporting = (CheckBoxPreference) prefSet.findPreference(ANONYMOUS_OPT_IN);
+ mViewStats = (Preference) prefSet.findPreference(VIEW_STATS);
+ boolean firstBoot = mPrefs.getBoolean(ANONYMOUS_FIRST_BOOT, true);
+ if (mEnableReporting.isChecked() && firstBoot) {
+ mPrefs.edit().putBoolean(ANONYMOUS_FIRST_BOOT, false).apply();
+ ReportingServiceManager.launchService(getActivity());
+ }
+ NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.cancel(1);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+ if (preference == mEnableReporting) {
+ if (mEnableReporting.isChecked()) {
+ // Display the confirmation dialog
+ mOkClicked = false;
+ if (mOkDialog != null) {
+ mOkDialog.dismiss();
+ mOkDialog = null;
+ }
+ mOkDialog = new AlertDialog.Builder(getActivity()).setMessage(
+ getActivity().getResources().getString(R.string.anonymous_statistics_warning))
+ .setTitle(R.string.anonymous_statistics_warning_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setPositiveButton(android.R.string.yes, this)
+ .setNeutralButton(getString(R.string.anonymous_learn_more), this)
+ .setNegativeButton(android.R.string.no, this)
+ .show();
+ mOkDialog.setOnDismissListener(this);
+ } else {
+ // Disable reporting
+ mPrefs.edit().putBoolean(ANONYMOUS_OPT_IN, false).apply();
+ }
+ } else if (preference == mViewStats) {
+ // Display the stats page
+ Uri uri = Uri.parse("http://stats.cyanogenmod.com");
+ startActivity(new Intent(Intent.ACTION_VIEW, uri));
+ } else {
+ // If we didn't handle it, let preferences handle it.
+ return super.onPreferenceTreeClick(preferenceScreen, preference);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ return false;
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (!mOkClicked) {
+ mEnableReporting.setChecked(false);
+ }
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ mOkClicked = true;
+ mPrefs.edit().putBoolean(ANONYMOUS_OPT_IN, true).apply();
+ ReportingServiceManager.launchService(getActivity());
+ } else if (which == DialogInterface.BUTTON_NEGATIVE){
+ mEnableReporting.setChecked(false);
+ } else {
+ Uri uri = Uri.parse("http://www.cyanogenmod.com/blog/cmstats-what-it-is-and-why-you-should-opt-in");
+ startActivity(new Intent(Intent.ACTION_VIEW, uri));
+ }
+ }
+
+}
diff --git a/src/com/android/settings/cmstats/PreviewData.java b/src/com/android/settings/cmstats/PreviewData.java
new file mode 100644
index 0000000..c8b18ba
--- /dev/null
+++ b/src/com/android/settings/cmstats/PreviewData.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod 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.
+ */
+
+package com.android.settings.cmstats;
+
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+public class PreviewData extends SettingsPreferenceFragment
+ implements Preference.OnPreferenceChangeListener{
+
+ private static final String UNIQUE_ID = "preview_id";
+
+ private static final String DEVICE = "preview_device";
+
+ private static final String VERSION = "preview_version";
+
+ private static final String COUNTRY = "preview_country";
+
+ private static final String CARRIER = "preview_carrier";
+
+ private Preference mId;
+
+ private Preference mDevice;
+
+ private Preference mVersion;
+
+ private Preference mCountry;
+
+ private Preference mCarrier;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (getPreferenceManager() != null) {
+
+ addPreferencesFromResource(R.xml.preview_data);
+ PreferenceScreen prefSet = getPreferenceScreen();
+
+ mId = (Preference) prefSet.findPreference(UNIQUE_ID);
+ mDevice = (Preference) prefSet.findPreference(DEVICE);
+ mVersion = (Preference) prefSet.findPreference(VERSION);
+ mCountry = (Preference) prefSet.findPreference(COUNTRY);
+ mCarrier = (Preference) prefSet.findPreference(CARRIER);
+
+ mId.setSummary(Utilities.getUniqueID(getActivity().getApplicationContext()));
+ mDevice.setSummary(Utilities.getDevice());
+ mVersion.setSummary(Utilities.getModVersion());
+ mCountry.setSummary(Utilities.getCountryCode(getActivity().getApplicationContext()));
+ mCarrier.setSummary(Utilities.getCarrier(getActivity().getApplicationContext()));
+ }
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ return false;
+ }
+}
diff --git a/src/com/android/settings/cmstats/ReportingService.java b/src/com/android/settings/cmstats/ReportingService.java
new file mode 100644
index 0000000..da2e9e6
--- /dev/null
+++ b/src/com/android/settings/cmstats/ReportingService.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod 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.
+ */
+
+package com.android.settings.cmstats;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.Settings;
+
+public class ReportingService extends Service {
+ protected static final String TAG = "CMStats";
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand (Intent intent, int flags, int startId) {
+ if (intent.getBooleanExtra("firstBoot", false)) {
+ promptUser();
+ Log.d(TAG, "Prompting user for opt-in.");
+ } else {
+ Log.d(TAG, "User has opted in -- reporting.");
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ report();
+ }
+ };
+ thread.start();
+ }
+ return Service.START_REDELIVER_INTENT;
+ }
+
+ private void report() {
+ String deviceId = Utilities.getUniqueID(getApplicationContext());
+ String deviceName = Utilities.getDevice();
+ String deviceVersion = Utilities.getModVersion();
+ String deviceCountry = Utilities.getCountryCode(getApplicationContext());
+ String deviceCarrier = Utilities.getCarrier(getApplicationContext());
+ String deviceCarrierId = Utilities.getCarrierId(getApplicationContext());
+
+ Log.d(TAG, "SERVICE: Device ID=" + deviceId);
+ Log.d(TAG, "SERVICE: Device Name=" + deviceName);
+ Log.d(TAG, "SERVICE: Device Version=" + deviceVersion);
+ Log.d(TAG, "SERVICE: Country=" + deviceCountry);
+ Log.d(TAG, "SERVICE: Carrier=" + deviceCarrier);
+ Log.d(TAG, "SERVICE: Carrier ID=" + deviceCarrierId);
+
+ HttpClient httpclient = new DefaultHttpClient();
+ HttpPost httppost = new HttpPost("http://stats.cyanogenmod.com/submit");
+ try {
+ List<NameValuePair> kv = new ArrayList<NameValuePair>(5);
+ kv.add(new BasicNameValuePair("device_hash", deviceId));
+ kv.add(new BasicNameValuePair("device_name", deviceName));
+ kv.add(new BasicNameValuePair("device_version", deviceVersion));
+ kv.add(new BasicNameValuePair("device_country", deviceCountry));
+ kv.add(new BasicNameValuePair("device_carrier", deviceCarrier));
+ kv.add(new BasicNameValuePair("device_carrier_id", deviceCarrierId));
+ httppost.setEntity(new UrlEncodedFormEntity(kv));
+ httpclient.execute(httppost);
+ getSharedPreferences("CMStats", 0).edit().putLong(AnonymousStats.ANONYMOUS_LAST_CHECKED,
+ System.currentTimeMillis()).apply();
+ } catch (Exception e) {
+ Log.e(TAG, "Got Exception", e);
+ }
+ ReportingServiceManager.setAlarm(this);
+ stopSelf();
+ }
+
+ private void promptUser() {
+ NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ Intent nI = new Intent();
+ nI.setComponent(new ComponentName(getPackageName(),Settings.AnonymousStatsActivity.class.getName()));
+ PendingIntent pI = PendingIntent.getActivity(this, 0, nI, 0);
+ Notification.Builder builder = new Notification.Builder(this)
+ .setSmallIcon(R.drawable.ic_cm_stats_notif)
+ .setAutoCancel(true)
+ .setTicker(getString(R.string.anonymous_statistics_title))
+ .setContentIntent(pI)
+ .setWhen(0)
+ .setContentTitle(getString(R.string.anonymous_statistics_title))
+ .setContentText(getString(R.string.anonymous_notification_desc));
+ nm.notify(1, builder.getNotification());
+ }
+}
diff --git a/src/com/android/settings/cmstats/ReportingServiceManager.java b/src/com/android/settings/cmstats/ReportingServiceManager.java
new file mode 100644
index 0000000..41f563d
--- /dev/null
+++ b/src/com/android/settings/cmstats/ReportingServiceManager.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod 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.
+ */
+
+package com.android.settings.cmstats;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.util.Log;
+
+public class ReportingServiceManager extends BroadcastReceiver {
+
+ public static final long dMill = 24 * 60 * 60 * 1000;
+ public static final long tFrame = 7 * dMill;
+
+ @Override
+ public void onReceive(Context ctx, Intent intent) {
+ if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
+ setAlarm(ctx);
+ } else {
+ launchService(ctx);
+ }
+ }
+
+ protected static void setAlarm (Context ctx) {
+ SharedPreferences prefs = ctx.getSharedPreferences("CMStats", 0);
+ prefs.edit().putBoolean(AnonymousStats.ANONYMOUS_ALARM_SET, false).apply();
+ boolean optedIn = prefs.getBoolean(AnonymousStats.ANONYMOUS_OPT_IN, true);
+ boolean firstBoot = prefs.getBoolean(AnonymousStats.ANONYMOUS_FIRST_BOOT, true);
+ if (!optedIn || firstBoot) {
+ return;
+ }
+ long lastSynced = prefs.getLong(AnonymousStats.ANONYMOUS_LAST_CHECKED, 0);
+ if (lastSynced == 0) {
+ return;
+ }
+ long timeLeft = (lastSynced + tFrame) - System.currentTimeMillis();
+ Intent sIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+ sIntent.setComponent(new ComponentName(ctx.getPackageName(), ReportingServiceManager.class.getName()));
+ AlarmManager alarmManager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
+ alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeLeft, PendingIntent.getBroadcast(ctx, 0, sIntent, 0));
+ Log.d(ReportingService.TAG, "Next sync attempt in : " + timeLeft / dMill + " days");
+ prefs.edit().putBoolean(AnonymousStats.ANONYMOUS_ALARM_SET, true).apply();
+ }
+
+ public static void launchService (Context ctx) {
+ ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo networkInfo = cm.getActiveNetworkInfo();
+ if (networkInfo != null && networkInfo.isConnected()) {
+ SharedPreferences prefs = ctx.getSharedPreferences("CMStats", 0);
+ long lastSynced = prefs.getLong(AnonymousStats.ANONYMOUS_LAST_CHECKED, 0);
+ boolean firstBoot = prefs.getBoolean(AnonymousStats.ANONYMOUS_FIRST_BOOT, true);
+ boolean optedIn = prefs.getBoolean(AnonymousStats.ANONYMOUS_OPT_IN, true);
+ boolean alarmSet = prefs.getBoolean(AnonymousStats.ANONYMOUS_ALARM_SET, false);
+ if (alarmSet) {
+ return;
+ }
+ boolean shouldSync = false;
+ if (lastSynced == 0) {
+ shouldSync = true;
+ } else if (System.currentTimeMillis() - lastSynced >= tFrame) {
+ shouldSync = true;
+ }
+ if ((shouldSync && optedIn) || firstBoot) {
+ Intent sIntent = new Intent();
+ sIntent.setComponent(new ComponentName(ctx.getPackageName(), ReportingService.class.getName()));
+ sIntent.putExtra("firstBoot", firstBoot);
+ ctx.startService(sIntent);
+ } else if (optedIn) {
+ setAlarm(ctx);
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/cmstats/Utilities.java b/src/com/android/settings/cmstats/Utilities.java
new file mode 100644
index 0000000..5e598db
--- /dev/null
+++ b/src/com/android/settings/cmstats/Utilities.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod 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.
+ */
+
+package com.android.settings.cmstats;
+
+import java.math.BigInteger;
+import java.net.NetworkInterface;
+import java.security.MessageDigest;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.telephony.TelephonyManager;
+
+public class Utilities {
+ public static String getUniqueID(Context ctx) {
+ TelephonyManager tm = (TelephonyManager) ctx
+ .getSystemService(Context.TELEPHONY_SERVICE);
+
+ String device_id = digest(tm.getDeviceId());
+ if (device_id == null) {
+ String wifiInterface = SystemProperties.get("wifi.interface");
+ try {
+ String wifiMac = new String(NetworkInterface.getByName(
+ wifiInterface).getHardwareAddress());
+ device_id = digest(wifiMac);
+ } catch (Exception e) {
+ device_id = null;
+ }
+ }
+
+ return device_id;
+ }
+
+ public static String getCarrier(Context ctx) {
+ TelephonyManager tm = (TelephonyManager) ctx
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ String carrier = tm.getNetworkOperatorName();
+ if ("".equals(carrier)) {
+ carrier = "Unknown";
+ }
+ return carrier;
+ }
+
+ public static String getCarrierId(Context ctx) {
+ TelephonyManager tm = (TelephonyManager) ctx
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ String carrierId = tm.getNetworkOperator();
+ if ("".equals(carrierId)) {
+ carrierId = "0";
+ }
+ return carrierId;
+ }
+
+ public static String getCountryCode(Context ctx) {
+ TelephonyManager tm = (TelephonyManager) ctx
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ String countryCode = tm.getNetworkCountryIso();
+ if (countryCode.equals("")) {
+ countryCode = "Unknown";
+ }
+ return countryCode;
+ }
+
+ public static String getDevice() {
+ return SystemProperties.get("ro.cm.device");
+ }
+
+ public static String getModVersion() {
+ return SystemProperties.get("ro.cm.version");
+ }
+
+ public static String digest(String input) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ return new BigInteger(1, md.digest(input.getBytes())).toString(16)
+ .toUpperCase();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}