Android-x86
Fork
Faire un don

  • R/O
  • HTTP
  • SSH
  • HTTPS

packages-services-Analytics: Commit

packages/services/Analytics


Commit MetaInfo

Révision1e4bc49f0f1339d7c9f417b73ff359daf5dd1468 (tree)
l'heure2016-08-10 18:48:27
AuteurHugo <hugo@jide...>
CommiterChih-Wei Huang

Message de Log

HardwareCollector: send hardware information to GA

This app/service will collect informations about device hardware after
boot completed and send these informations to AnalyticsService that will
in turn anonymously send these informations to Google Analytics servers.

Change Summary

Modification

--- /dev/null
+++ b/HardwareCollector/Android.mk
@@ -0,0 +1,14 @@
1+LOCAL_PATH := $(call my-dir)
2+
3+include $(CLEAR_VARS)
4+
5+LOCAL_MODULE_TAGS := optional
6+LOCAL_STATIC_JAVA_LIBRARIES := analytics-utils
7+
8+LOCAL_SRC_FILES := $(call all-java-files-under, src)
9+
10+LOCAL_PACKAGE_NAME := HardwareCollector
11+LOCAL_CERTIFICATE := platform
12+LOCAL_PRIVILEGED_MODULE := true
13+
14+include $(BUILD_PACKAGE)
--- /dev/null
+++ b/HardwareCollector/AndroidManifest.xml
@@ -0,0 +1,32 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<!-- Copyright (C) 2016 Jide Technology Ltd.
3+
4+ Licensed under the Apache License, Version 2.0 (the "License");
5+ you may not use this file except in compliance with the License.
6+ You may obtain a copy of the License at
7+
8+ http://www.apache.org/licenses/LICENSE-2.0
9+
10+ Unless required by applicable law or agreed to in writing, software
11+ distributed under the License is distributed on an "AS IS" BASIS,
12+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ See the License for the specific language governing permissions and
14+ limitations under the License.
15+-->
16+
17+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
18+ package="org.android_x86.hardwarecollector">
19+
20+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
21+ <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
22+ <uses-permission android:name="android.permission.RESTART_PACKAGES"/>
23+ <application android:label="@string/app_name">
24+ <service android:name=".HardwareCollectorService"
25+ android:exported="true"/>
26+ <receiver android:name=".BootCompletedReceiver">
27+ <intent-filter>
28+ <action android:name="android.intent.action.BOOT_COMPLETED" />
29+ </intent-filter>
30+ </receiver>
31+ </application>
32+</manifest>
--- /dev/null
+++ b/HardwareCollector/res/values/strings.xml
@@ -0,0 +1,18 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<!-- Copyright (C) 2016 Jide Technology Ltd.
3+
4+ Licensed under the Apache License, Version 2.0 (the "License");
5+ you may not use this file except in compliance with the License.
6+ You may obtain a copy of the License at
7+
8+ http://www.apache.org/licenses/LICENSE-2.0
9+
10+ Unless required by applicable law or agreed to in writing, software
11+ distributed under the License is distributed on an "AS IS" BASIS,
12+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ See the License for the specific language governing permissions and
14+ limitations under the License.
15+-->
16+<resources>
17+ <string name="app_name">HardwareCollector</string>
18+</resources>
--- /dev/null
+++ b/HardwareCollector/src/org/android_x86/hardwarecollector/BootCompletedReceiver.java
@@ -0,0 +1,30 @@
1+/*
2+ * Copyright 2016 Jide Technology Ltd.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+package org.android_x86.hardwarecollector;
17+
18+import android.content.BroadcastReceiver;
19+import android.content.Context;
20+import android.content.Intent;
21+
22+public class BootCompletedReceiver extends BroadcastReceiver {
23+ @Override
24+ public void onReceive(Context context, Intent data) {
25+ String action = data.getAction();
26+ Intent startIntent = new Intent(context, HardwareCollectorService.class);
27+ startIntent.setAction(action);
28+ context.startService(startIntent);
29+ }
30+}
--- /dev/null
+++ b/HardwareCollector/src/org/android_x86/hardwarecollector/HardwareCollectorService.java
@@ -0,0 +1,247 @@
1+/*
2+ * Copyright 2016 Jide Technology Ltd.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+package org.android_x86.hardwarecollector;
17+
18+import org.android_x86.analytics.AnalyticsHelper;
19+import org.android_x86.analytics.GeneralLogs;
20+
21+import android.app.IntentService;
22+import android.content.Context;
23+import android.content.Intent;
24+import android.content.IntentFilter;
25+import android.graphics.SurfaceTexture;
26+import android.hardware.input.InputManager;
27+import android.opengl.EGL14;
28+import android.opengl.GLES20;
29+import android.util.Log;
30+import android.view.InputDevice;
31+
32+import org.json.JSONObject;
33+
34+import javax.microedition.khronos.egl.EGL10;
35+import javax.microedition.khronos.egl.EGLConfig;
36+import javax.microedition.khronos.egl.EGLContext;
37+import javax.microedition.khronos.egl.EGLDisplay;
38+import javax.microedition.khronos.egl.EGLSurface;
39+import java.io.BufferedReader;
40+import java.io.File;
41+import java.io.FileReader;
42+import java.io.FileWriter;
43+import java.io.IOException;
44+import java.io.PrintWriter;
45+
46+public class HardwareCollectorService extends IntentService {
47+ private static final String TAG = "HardwareCollectorService";
48+
49+ private static final String GA_CATEGORY = "hardware_info";
50+ private static final String GA_ACTION_GPU_RENDERER = "gpu_renderer";
51+ private static final String GA_ACTION_CPU_MODEL = "cpu_model";
52+ private static final String GA_ACTION_TOUCH_SCREEN_NAME = "touch_screen_name";
53+ private static final String GA_ACTION_HAS_BATTERY = "has_battery";
54+ private static final String GA_LABEL_HAS_BATTERY = "battery";
55+ private static final String GA_LABEL_NO_BATTERY = "no_battery";
56+
57+ private static final String LAST_INFO_FILE_NAME = "lastInfo.json";
58+ private static final String CPU_INFO_FILE = "/proc/cpuinfo";
59+ private static final String CPU_INFO_MODEL_NAME_PRE = "model name\t: ";
60+ private static final int TOUCHSCREEN_SOURCE_BIT = 4098;
61+
62+ private Context mContext;
63+ private File mInfoFile;
64+ private JSONObject mInfoJson;
65+
66+ public HardwareCollectorService() {
67+ super("HardwareCollectorService");
68+ }
69+
70+ @Override
71+ public void onCreate() {
72+ super.onCreate();
73+ mContext = getBaseContext();
74+ mInfoFile = new File(getApplicationContext().getFilesDir(), LAST_INFO_FILE_NAME);
75+ }
76+
77+ @Override
78+ protected void onHandleIntent(Intent intent) {
79+ String action = intent.getAction();
80+ Log.i(TAG, "handle intent:" + intent);
81+ if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
82+ uploadHardwareInfo();
83+ }
84+ }
85+
86+ private void uploadHardwareInfo() {
87+ getLastInfo();
88+ collectOpenGLInfo();
89+ collectCPUInfo();
90+ collectTouchScreenInfo();
91+ collectBatteryInfo();
92+ }
93+
94+ private void collectOpenGLInfo() {
95+ try {
96+ EGL10 egl = (EGL10) EGLContext.getEGL();
97+ EGLSurface eglSurface = null;
98+ EGLContext eglContext = null;
99+
100+ // initialize display
101+ EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
102+ int[] iparam = new int[2];
103+ egl.eglInitialize(eglDisplay, iparam);
104+
105+ // choose config
106+ EGLConfig[] eglConfigs = new EGLConfig[1];
107+ final int[] configSpec =
108+ {EGL10.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE};
109+ if (egl.eglChooseConfig(eglDisplay, configSpec, eglConfigs, 1, iparam)
110+ && iparam[0] > 0) {
111+ // create surface
112+ SurfaceTexture surfaceTexture = new SurfaceTexture(0);
113+ eglSurface = egl.eglCreateWindowSurface(
114+ eglDisplay, eglConfigs[0], surfaceTexture, null);
115+ if (eglSurface != null && eglSurface != EGL10.EGL_NO_SURFACE) {
116+ // create context
117+ final int[] attribList = {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
118+ eglContext = egl.eglCreateContext(
119+ eglDisplay, eglConfigs[0], EGL10.EGL_NO_CONTEXT, attribList);
120+ egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
121+ }
122+ }
123+
124+ checkAndSend(GA_ACTION_GPU_RENDERER, GLES20.glGetString(GLES20.GL_RENDERER));
125+ } catch (Exception e) {
126+ Log.e(TAG, "fail to get GPU renderer", e);
127+ }
128+ }
129+
130+ private void collectCPUInfo() {
131+ try {
132+ BufferedReader reader = new BufferedReader(new FileReader(CPU_INFO_FILE));
133+ String cpuInfo;
134+ String model = null;
135+ while ((cpuInfo = reader.readLine()) != null) {
136+ if (cpuInfo.contains(CPU_INFO_MODEL_NAME_PRE)) {
137+ model = cpuInfo.substring(CPU_INFO_MODEL_NAME_PRE.length());
138+ checkAndSend(GA_ACTION_CPU_MODEL, model);
139+ break;
140+ }
141+ }
142+ reader.close();
143+ } catch (Exception e) {
144+ Log.e(TAG, "fail to get CPU model name", e);
145+ }
146+ }
147+
148+ private void collectTouchScreenInfo() {
149+ int[] ids = InputManager.getInstance().getInputDeviceIds();
150+ for (int id : ids) {
151+ InputDevice device = InputManager.getInstance().getInputDevice(id);
152+ String name = device.getName();
153+ if ((device.getSources() & TOUCHSCREEN_SOURCE_BIT) == TOUCHSCREEN_SOURCE_BIT) {
154+ checkAndSend(GA_ACTION_TOUCH_SCREEN_NAME, name);
155+ break;
156+ }
157+ }
158+ }
159+
160+ private void collectBatteryInfo() {
161+ IntentFilter filter = new IntentFilter();
162+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
163+ Intent batteryIntent = mContext.registerReceiver(null, filter);
164+ String label = batteryIntent.getBooleanExtra("present", false) ?
165+ GA_LABEL_HAS_BATTERY : GA_LABEL_NO_BATTERY;
166+ AnalyticsHelper.CustomEvent customEvent = AnalyticsHelper.newSystemCoreEvent(
167+ mContext, GA_CATEGORY, GA_ACTION_HAS_BATTERY);
168+ customEvent.setLabel(label);
169+ customEvent.sendWithSampling();
170+ }
171+
172+ private void getLastInfo() {
173+ try {
174+ if (mInfoFile.exists()) {
175+ String fileString = readFileAsString(mInfoFile.getPath());
176+ mInfoJson = new JSONObject(fileString);
177+ } else {
178+ mInfoJson = new JSONObject();
179+ }
180+ } catch (Exception e) {
181+ Log.e(TAG, "fail to get last info file", e);
182+ }
183+ }
184+
185+ private boolean isDifferentInfo(String key, String value) {
186+ try {
187+ if (mInfoJson.has(key)) {
188+ String lastValue = mInfoJson.getString(key);
189+ return lastValue == null || !lastValue.equals(value);
190+ }
191+ } catch (Exception e) {
192+ Log.e(TAG, "check info failed", e);
193+ }
194+ return true;
195+ }
196+
197+ private void checkAndSend(String key, String value) {
198+ if (isDifferentInfo(key, value)) {
199+ sendToGA(key, value);
200+ saveInfo(key, value);
201+ }
202+ }
203+
204+ private void sendToGA(String action, String label) {
205+ AnalyticsHelper.CustomEvent customEvent =
206+ AnalyticsHelper.newSystemCoreEvent(mContext, GA_CATEGORY, action);
207+ customEvent.setLabel(label);
208+ customEvent.sendWithoutSampling();
209+ }
210+
211+ private void sendToAnalytics(String key, String value) {
212+ GeneralLogs logs = new GeneralLogs();
213+ logs.set(key, value);
214+ AnalyticsHelper.uploadLogToLogServer(mContext, logs);
215+ }
216+
217+ private void saveInfo(String key, String value) {
218+ try {
219+ mInfoJson.put(key, value);
220+ writeStringToFile(mInfoFile.getPath(), mInfoJson.toString());
221+ } catch (Exception e) {
222+ Log.e(TAG, "write info file failed", e);
223+ }
224+ }
225+
226+ public static void writeStringToFile(String filePath, String sets) throws IOException {
227+ FileWriter fileWriter = new FileWriter(filePath);
228+ PrintWriter out = new PrintWriter(fileWriter);
229+ out.write(sets);
230+ out.println();
231+ fileWriter.close();
232+ out.close();
233+ }
234+
235+ private static String readFileAsString(String filePath) throws IOException {
236+ StringBuffer fileData = new StringBuffer();
237+ BufferedReader reader = new BufferedReader(new FileReader(filePath));
238+ char[] buf = new char[1024];
239+ int count = 0;
240+ while ((count = reader.read(buf)) != -1) {
241+ String readData = String.valueOf(buf, 0, count);
242+ fileData.append(readData);
243+ }
244+ reader.close();
245+ return fileData.toString();
246+ }
247+}
Afficher sur ancien navigateur de dépôt.