diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 74956b0..42ecdbd 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,93 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + package="com.henny.PowerTutor2" + android:versionCode="19" + android:versionName="2" > - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README b/README index c9875c4..0847f2a 100644 --- a/README +++ b/README @@ -2,9 +2,7 @@ PowerTutor Project Model based power mobile power estimator by application -Contact: powertutor@umich.edu - -Website: http://powertutor.org +Contact: henny@uni-koblenz.de This package includes the PowerTutor source code. The code responsible for uploading logs to our remote server has been removed and replaced by a stub that diff --git a/libs/android-support-v4.jar b/libs/android-support-v4.jar new file mode 100644 index 0000000..9056828 Binary files /dev/null and b/libs/android-support-v4.jar differ diff --git a/libs/google-play-services_lib/.classpath b/libs/google-play-services_lib/.classpath new file mode 100644 index 0000000..5176974 --- /dev/null +++ b/libs/google-play-services_lib/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/libs/google-play-services_lib/.gitignore b/libs/google-play-services_lib/.gitignore new file mode 100644 index 0000000..2b34c40 --- /dev/null +++ b/libs/google-play-services_lib/.gitignore @@ -0,0 +1,19 @@ +# files for the dex VM +*.dex + +# Java class files +*.class + +# generated files +bin/ +gen/ + +# Ignore gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ \ No newline at end of file diff --git a/libs/google-play-services_lib/.project b/libs/google-play-services_lib/.project new file mode 100644 index 0000000..06ae985 --- /dev/null +++ b/libs/google-play-services_lib/.project @@ -0,0 +1,33 @@ + + + google-play-services_lib + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/libs/google-play-services_lib/.settings/org.eclipse.jdt.core.prefs b/libs/google-play-services_lib/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b080d2d --- /dev/null +++ b/libs/google-play-services_lib/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/libs/google-play-services_lib/AndroidManifest.xml b/libs/google-play-services_lib/AndroidManifest.xml new file mode 100644 index 0000000..99c96a3 --- /dev/null +++ b/libs/google-play-services_lib/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/libs/google-play-services_lib/README.txt b/libs/google-play-services_lib/README.txt new file mode 100644 index 0000000..32f8d5e --- /dev/null +++ b/libs/google-play-services_lib/README.txt @@ -0,0 +1,17 @@ +Library Project including Google Play services client jar. + +This can be used by an Android project to use the API's provided +by Google Play services. + +There is technically no source, but the src folder is necessary +to ensure that the build system works. The content is actually +located in the libs/ directory. + + +USAGE: + +Make sure you import this Android library project into your IDE +and set this project as a dependency. + +Note that if you use proguard, you will want to include the +options from proguard.txt in your configuration. \ No newline at end of file diff --git a/libs/google-play-services_lib/libs/google-play-services.jar b/libs/google-play-services_lib/libs/google-play-services.jar new file mode 100644 index 0000000..dff6f7c Binary files /dev/null and b/libs/google-play-services_lib/libs/google-play-services.jar differ diff --git a/libs/google-play-services_lib/libs/google-play-services.jar.properties b/libs/google-play-services_lib/libs/google-play-services.jar.properties new file mode 100644 index 0000000..429687b --- /dev/null +++ b/libs/google-play-services_lib/libs/google-play-services.jar.properties @@ -0,0 +1 @@ +doc=../../../docs/reference diff --git a/libs/google-play-services_lib/proguard.txt b/libs/google-play-services_lib/proguard.txt new file mode 100644 index 0000000..0c9693a --- /dev/null +++ b/libs/google-play-services_lib/proguard.txt @@ -0,0 +1,20 @@ +-keep class * extends java.util.ListResourceBundle { + protected Object[][] getContents(); +} + +# Keep SafeParcelable value, needed for reflection. This is required to support backwards +# compatibility of some classes. +-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { + public static final *** NULL; +} + +# Keep the names of classes/members we need for client functionality. +-keepnames @com.google.android.gms.common.annotation.KeepName class * +-keepclassmembernames class * { + @com.google.android.gms.common.annotation.KeepName *; +} + +# Needed for Parcelable/SafeParcelable Creators to not get stripped +-keepnames class * implements android.os.Parcelable { + public static final ** CREATOR; +} \ No newline at end of file diff --git a/libs/google-play-services_lib/project.properties b/libs/google-play-services_lib/project.properties new file mode 100644 index 0000000..db721fd --- /dev/null +++ b/libs/google-play-services_lib/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-8 +android.library=true diff --git a/libs/google-play-services_lib/res/color/common_signin_btn_text_dark.xml b/libs/google-play-services_lib/res/color/common_signin_btn_text_dark.xml new file mode 100644 index 0000000..a615ba2 --- /dev/null +++ b/libs/google-play-services_lib/res/color/common_signin_btn_text_dark.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/libs/google-play-services_lib/res/color/common_signin_btn_text_light.xml b/libs/google-play-services_lib/res/color/common_signin_btn_text_light.xml new file mode 100644 index 0000000..6620668 --- /dev/null +++ b/libs/google-play-services_lib/res/color/common_signin_btn_text_light.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png new file mode 100644 index 0000000..0f9e791 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png new file mode 100644 index 0000000..570e432 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png new file mode 100644 index 0000000..570e432 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png new file mode 100644 index 0000000..0f9e791 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png new file mode 100644 index 0000000..f507b9f Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png new file mode 100644 index 0000000..d5625e5 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png new file mode 100644 index 0000000..aea3c0d Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png new file mode 100644 index 0000000..849e89f Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png new file mode 100644 index 0000000..f4ab2f2 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png new file mode 100644 index 0000000..9fe611d Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png new file mode 100644 index 0000000..bbcde39 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png new file mode 100644 index 0000000..53957b6 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png new file mode 100644 index 0000000..53957b6 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png new file mode 100644 index 0000000..bbcde39 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png new file mode 100644 index 0000000..000d12e Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png new file mode 100644 index 0000000..d927940 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png new file mode 100644 index 0000000..67f263c Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png new file mode 100644 index 0000000..96324c5 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png new file mode 100644 index 0000000..e450312 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png new file mode 100644 index 0000000..fb94b77 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_medium_off_client.png b/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_medium_off_client.png new file mode 100644 index 0000000..894f1b9 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_medium_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_small_off_client.png b/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_small_off_client.png new file mode 100644 index 0000000..ac77761 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_small_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_standard_off_client.png b/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_standard_off_client.png new file mode 100644 index 0000000..f1c32d3 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_standard_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_tall_off_client.png b/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_tall_off_client.png new file mode 100644 index 0000000..08a4670 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-hdpi/ic_plusone_tall_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png new file mode 100644 index 0000000..dddcbeb Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png new file mode 100644 index 0000000..58b75bd Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png new file mode 100644 index 0000000..58b75bd Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png new file mode 100644 index 0000000..dddcbeb Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png new file mode 100644 index 0000000..7d9ed78 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png new file mode 100644 index 0000000..0ca401d Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png new file mode 100644 index 0000000..f2c3f55 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png new file mode 100644 index 0000000..83b4fc9 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png new file mode 100644 index 0000000..dd74fe8 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png new file mode 100644 index 0000000..b7dc7aa Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png new file mode 100644 index 0000000..efdfe2e Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png new file mode 100644 index 0000000..c7650b0 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png new file mode 100644 index 0000000..c7650b0 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png new file mode 100644 index 0000000..efdfe2e Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png new file mode 100644 index 0000000..8c76283 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png new file mode 100644 index 0000000..abd26bc Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png new file mode 100644 index 0000000..28181c3 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png new file mode 100644 index 0000000..34957fa Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png new file mode 100644 index 0000000..e923ee9 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png new file mode 100644 index 0000000..34cf6bb Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_medium_off_client.png b/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_medium_off_client.png new file mode 100644 index 0000000..d7e5777 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_medium_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_small_off_client.png b/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_small_off_client.png new file mode 100644 index 0000000..af301c2 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_small_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_standard_off_client.png b/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_standard_off_client.png new file mode 100644 index 0000000..f43e965 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_standard_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_tall_off_client.png b/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_tall_off_client.png new file mode 100644 index 0000000..0b2b5c9 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-mdpi/ic_plusone_tall_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png new file mode 100644 index 0000000..9044a11 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png new file mode 100644 index 0000000..e94a49b Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png new file mode 100644 index 0000000..e94a49b Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png new file mode 100644 index 0000000..9044a11 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png new file mode 100644 index 0000000..bfe4f04 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png new file mode 100644 index 0000000..876884f Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png new file mode 100644 index 0000000..b3e6dd5 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png new file mode 100644 index 0000000..5a888f2 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png new file mode 100644 index 0000000..d0f7b4c Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png new file mode 100644 index 0000000..0db6b06 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png new file mode 100644 index 0000000..d182b5e Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png new file mode 100644 index 0000000..47e2aea Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png new file mode 100644 index 0000000..47e2aea Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png new file mode 100644 index 0000000..d182b5e Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png new file mode 100644 index 0000000..64e9706 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png new file mode 100644 index 0000000..0fd8cdd Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png new file mode 100644 index 0000000..3427b47 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png new file mode 100644 index 0000000..31e38c4 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png new file mode 100644 index 0000000..e6a7880 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png new file mode 100644 index 0000000..972962d Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_medium_off_client.png b/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_medium_off_client.png new file mode 100644 index 0000000..bb93309 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_medium_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_small_off_client.png b/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_small_off_client.png new file mode 100644 index 0000000..6174fcd Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_small_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_standard_off_client.png b/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_standard_off_client.png new file mode 100644 index 0000000..6a4c298 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_standard_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_tall_off_client.png b/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_tall_off_client.png new file mode 100644 index 0000000..f68e913 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xhdpi/ic_plusone_tall_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.png new file mode 100644 index 0000000..9044a11 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.png new file mode 100644 index 0000000..e94a49b Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.png new file mode 100644 index 0000000..e94a49b Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.png new file mode 100644 index 0000000..9044a11 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_disabled_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.png new file mode 100644 index 0000000..bfe4f04 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.png new file mode 100644 index 0000000..876884f Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.png new file mode 100644 index 0000000..b3e6dd5 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_normal_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.png new file mode 100644 index 0000000..5a888f2 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_normal_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.png new file mode 100644 index 0000000..d0f7b4c Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_pressed_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.png new file mode 100644 index 0000000..0db6b06 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_icon_pressed_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.png new file mode 100644 index 0000000..d182b5e Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.png new file mode 100644 index 0000000..47e2aea Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.png new file mode 100644 index 0000000..47e2aea Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.png new file mode 100644 index 0000000..d182b5e Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_disabled_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.png new file mode 100644 index 0000000..64e9706 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_focus_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.png new file mode 100644 index 0000000..0fd8cdd Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_focus_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.png new file mode 100644 index 0000000..3427b47 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_normal_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.png new file mode 100644 index 0000000..31e38c4 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_normal_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.png new file mode 100644 index 0000000..e6a7880 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_pressed_dark.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.png b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.png new file mode 100644 index 0000000..972962d Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/common_signin_btn_text_pressed_light.9.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_medium_off_client.png b/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_medium_off_client.png new file mode 100644 index 0000000..4f23739 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_medium_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_small_off_client.png b/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_small_off_client.png new file mode 100644 index 0000000..8ffa1d7 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_small_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_standard_off_client.png b/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_standard_off_client.png new file mode 100644 index 0000000..4d81cf4 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_standard_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_tall_off_client.png b/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_tall_off_client.png new file mode 100644 index 0000000..fab5a79 Binary files /dev/null and b/libs/google-play-services_lib/res/drawable-xxhdpi/ic_plusone_tall_off_client.png differ diff --git a/libs/google-play-services_lib/res/drawable/common_signin_btn_icon_dark.xml b/libs/google-play-services_lib/res/drawable/common_signin_btn_icon_dark.xml new file mode 100644 index 0000000..dd1cf67 --- /dev/null +++ b/libs/google-play-services_lib/res/drawable/common_signin_btn_icon_dark.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/libs/google-play-services_lib/res/drawable/common_signin_btn_icon_light.xml b/libs/google-play-services_lib/res/drawable/common_signin_btn_icon_light.xml new file mode 100644 index 0000000..abf412b --- /dev/null +++ b/libs/google-play-services_lib/res/drawable/common_signin_btn_icon_light.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/libs/google-play-services_lib/res/drawable/common_signin_btn_text_dark.xml b/libs/google-play-services_lib/res/drawable/common_signin_btn_text_dark.xml new file mode 100644 index 0000000..2d92217 --- /dev/null +++ b/libs/google-play-services_lib/res/drawable/common_signin_btn_text_dark.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/libs/google-play-services_lib/res/drawable/common_signin_btn_text_light.xml b/libs/google-play-services_lib/res/drawable/common_signin_btn_text_light.xml new file mode 100644 index 0000000..810c021 --- /dev/null +++ b/libs/google-play-services_lib/res/drawable/common_signin_btn_text_light.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/libs/google-play-services_lib/res/values-af/strings.xml b/libs/google-play-services_lib/res/values-af/strings.xml new file mode 100644 index 0000000..1b211f5 --- /dev/null +++ b/libs/google-play-services_lib/res/values-af/strings.xml @@ -0,0 +1,31 @@ + + + "Kry Google Play-dienste" + "Hierdie program sal nie loop sonder Google Play-dienste nie, wat nie op jou foon is nie." + "Hierdie program sal nie loop sonder Google Play-dienste nie, wat nie op jou tablet is nie." + "Kry Google Play-dienste" + "Aktiveer Google Play-dienste" + "Hierdie program sal nie werk tensy jy Google Play-dienste aktiveer nie." + "Aktiveer Google Play-dienste" + "Dateer Google Play-dienste op" + "Hierdie program sal nie loop nie, tensy jy Google Play-dienste opdateer." + "Netwerkfout" + "\'n Dataverbinding is nodig om aan Google Play-dienste te koppel." + "Ongeldige rekening" + "Die gespesifiseerde rekening bestaan nie op hierdie toestel nie. Kies asseblief \'n ander rekening." + "Onbekende probleem met Google Play-dienste." + "Google Play-dienste" + "Google Play-dienste, waarop sommige van jou programme staatmaak, werk nie met jou toestel nie. Kontak asseblief die vervaardiger vir bystand." + "Dit lyk of die datum op die toestel verkeerd is. Gaan asseblief die datum op die toestel na." + "Dateer op" + "Meld aan" + "Meld aan met Google" + + "\'n Program het probeer om \'n slegte weergawe van Google Play-dienste te gebruik." + "\'n Program vereis dat Google Play-dienste geaktiveer word." + "\'n Program vereis dat Google Play-dienste geïnstalleer word." + "\'n Program vereis \'n opdatering vir Google Play-dienste." + "Google Play-dienstefout" + "Versoek deur %1$s" + diff --git a/libs/google-play-services_lib/res/values-am/strings.xml b/libs/google-play-services_lib/res/values-am/strings.xml new file mode 100644 index 0000000..2585210 --- /dev/null +++ b/libs/google-play-services_lib/res/values-am/strings.xml @@ -0,0 +1,31 @@ + + + "Google Play አገልግሎቶችን አግኝ" + "ይህ መተግበሪያ ያለ Google Play አገልግሎቶች አይሰራም፣ እነሱ ደግሞ ስልክዎ ላይ የሉም።" + "ይህ መተግበሪያ ያለ Google Play አገልግሎቶች አይሰራም፣ እነሱ ደግሞ ጡባዊዎ ላይ የሉም።" + "Google Play አገልግሎቶችን አግኝ" + "Google Play አገልግሎቶችን አንቃ" + "Google Play አገልግሎቶችን እስካላነቁ ድረስ ይህ መተግበሪያ አይሰራም።" + "Google Play አገልግሎቶችን አንቃ" + "Google Play አገልግሎቶችን ያዘምኑ" + "Google Play አገልግሎቶችን እስኪያዘምኑ ድረስ ይህ መተግበሪያ አይሰራም።" + "የአውታረ መረብ ስህተት" + "ከGoogle Play አገልግሎቶች ጋር ለመገናኘት የውሂብ ግንኙነት ያስፈልጋል።" + "ልክ ያልሆነ መለያ" + "የተገለጸው መለያ በዚህ መሣሪያ ላይ የለም። እባክው የተለየ መለያ ይምረጡ።" + "በGoogle Play አገልግሎቶች ላይ ያልታወቀ ችግር።" + "Google Play አገልግሎቶች" + "የGoogle Play አገልግሎቶች፣ አንዳንድ መተግበሪያዎችዎ በእሱ ላይ ጥገኛ የሆኑት፣ በመሣሪያዎ አይደገፍም። እባክዎ ለእርዳታ አምራቹን ያግኙ።" + "በመሣሪያው ላይ ያለው ቀን ትክክል አይመስልም። እባክዎ በመሣሪያው ላይ ያለውን ቀን ያረጋግጡ።" + "ያዘምኑ" + "ግባ" + "በGoogle ይግቡ" + + "መተግበሪያው የGoogle Play አገልግሎቶችን መጥፎ ስሪት ለመጠቀም ሞክሯል።" + "መተግበሪያው Google Play አገልግሎቶች እንዲነቁ ይፈልጋል።" + "መተግበሪያው Google Play አገልግሎቶች እንዲጫኑ ይፈልጋል።" + "መተግበሪያው Google Play አገልግሎቶች እንዲዘምን ይፈልጋል።" + "የGoogle Play አገልግሎቶች ስህተት" + "በ%1$s የተጠየቀ" + diff --git a/libs/google-play-services_lib/res/values-ar/strings.xml b/libs/google-play-services_lib/res/values-ar/strings.xml new file mode 100644 index 0000000..bbc10b7 --- /dev/null +++ b/libs/google-play-services_lib/res/values-ar/strings.xml @@ -0,0 +1,31 @@ + + + "الحصول على خدمات Google Play" + "لن يتم تشغيل هذا التطبيق بدون خدمات Google Play، والتي لا تتوفر في هاتفك." + "لن يتم تشغيل هذا التطبيق بدون خدمات Google Play، والتي لا تتوفر في جهازك اللوحي." + "الحصول على خدمات Google Play" + "تمكين خدمات Google Play" + "لن يعمل هذا التطبيق ما لم يتم تمكين خدمات Google Play." + "تمكين خدمات Google Play" + "تحديث خدمات Google Play" + "لن يتم تشغيل هذا التطبيق ما لم تحدِّث خدمات Google Play." + "خطأ في الشبكة" + "يتطلب الاتصال بخدمات Google Play وجود اتصال بيانات." + "حساب غير صالح" + "الحساب الذي تمّ تحديده غير موجود على الجهاز. يُرجى اختيار حساب آخر." + "حدثت مشكلة غير معروفة في خدمات Google Play." + "خدمات Google Play" + "خدمات Google Play التي تستجيب لها بعض تطبيقاتك لا تعمل على جهازك. يُرجى الاتصال بجهة التصنيع للحصول على المساعدة." + "يبدو أن التاريخ على الجهاز غير صحيح. الرجاء التحقق من التاريخ على الجهاز." + "تحديث" + "تسجيل الدخول" + "تسجيل الدخول باستخدام Google" + + "يحاول أحد التطبيقات استخدام إصدار غير صالح من خدمات Google Play." + "يتطلب أحد التطبيقات تمكين خدمات Google Play." + "يتطلب أحد التطبيقات تثبيت خدمات Google Play." + "يتطلب أحد التطبيقات تحديث خدمات Google Play." + "خطأ في خدمات Google Play" + "تم الطلب عن طريق %1$s" + diff --git a/libs/google-play-services_lib/res/values-be/strings.xml b/libs/google-play-services_lib/res/values-be/strings.xml new file mode 100644 index 0000000..81382d1 --- /dev/null +++ b/libs/google-play-services_lib/res/values-be/strings.xml @@ -0,0 +1,36 @@ + + + "Атрымаць службы Google Play" + "Гэта прыкладанне не будзе працаваць без службаў Google Play, якіх няма ў вашым тэлефоне." + "Гэта прыкладанне не будзе працаваць без службаў Google Play, якіх няма на вашым планшэце." + "Атрымаць службы Google Play" + "Уключыць службы Google Play" + "Гэта прыкладанне не будзе працаваць, пакуль вы не ўключыце службы Google Play." + "Уключыць службы Google Play" + "Абнаўленне службаў Google Play" + "Гэта прыкладанне не будзе працаваць падчас абнаўлення службаў Google Play." + + + + + + + + + "Невядомая праблема са службамі Google Play." + "Службы Google Play" + "Службы Google Play, да якiх прывязаны некаторыя прыкладаннi, не падтрымлiваюцца на вашай прыладзе. Па дапамогу звярнiцеся да вытворцы." + + + "Абнавіць" + "Увайсцi" + "Увайсці ў Google" + + "Прыкладанне паспрабавала скарыстацца сапсаванай версіяй службаў Google Play." + "Прыкладанне патрабуе ўключэння службаў Google Play." + "Прыкладанне патрабуе ўсталявання службаў Google Play." + "Прыкладанне патрабуе абнаўлення службаў Google Play." + "Памылка службаў Google Play" + "Запытана прыкладаннем %1$s" + diff --git a/libs/google-play-services_lib/res/values-bg/strings.xml b/libs/google-play-services_lib/res/values-bg/strings.xml new file mode 100644 index 0000000..bb8da3c --- /dev/null +++ b/libs/google-play-services_lib/res/values-bg/strings.xml @@ -0,0 +1,31 @@ + + + "Изтегляне на услугите за Google Play" + "Това приложение няма да се изпълнява без услугите за Google Play, които липсват в телефона ви." + "Това приложение няма да се изпълнява без услугите за Google Play, които липсват в таблета ви." + "Услуги за Google Play: Изтегл." + "Активиране на услугите за Google Play" + "Това приложение няма да работи, освен ако не активирате услугите за Google Play." + "Услуги за Google Play: Актив." + "Актуализиране на услугите за Google Play" + "Това приложение няма да се изпълнява, освен ако не актуализирате услугите за Google Play." + "Грешка в мрежата" + "За свързване с услугите за Google Play се изисква връзка за данни." + "Невалиден профил" + "Посоченият профил не съществува на това устройство. Моля, изберете друг." + "Неизвестен проблем с услугите за Google Play." + "Услуги за Google Play" + "Услугите за Google Play, на които разчитат някои от приложенията ви, не се поддържат от устройството ви. Моля, свържете се с производителя за помощ." + "Изглежда, че датата на устройството е неправилна. Моля, проверете я." + "Актуализиране" + "Вход" + "Вход с Google" + + "Приложение опита да ползва неправилна версия на услуг. за Google Play." + "Приложение изисква активирането на услугите за Google Play." + "Приложение изисква инсталирането на услугите за Google Play." + "Приложение изисква актуализирането на услугите за Google Play." + "Грешка в услугите за Google Play" + "Заявено от %1$s" + diff --git a/libs/google-play-services_lib/res/values-ca/strings.xml b/libs/google-play-services_lib/res/values-ca/strings.xml new file mode 100644 index 0000000..5b63e86 --- /dev/null +++ b/libs/google-play-services_lib/res/values-ca/strings.xml @@ -0,0 +1,31 @@ + + + "Baixa els serveis de Google Play" + "Aquesta aplicació no s\'executarà si el telèfon no té instal·lats els serveis de Google Play." + "Aquesta aplicació no funcionarà si la tauleta no té instal·lats els serveis de Google Play." + "Baixa els serveis de Google Play" + "Activa els serveis de Google Play" + "Aquesta aplicació no funcionarà si no actives els serveis de Google Play." + "Activa els serveis de Google Play" + "Actualitza els serveis de Google Play" + "Aquesta aplicació no s\'executarà si no actualitzes els serveis de Google Play." + "Error de xarxa" + "Es requereix una connexió de dades per connectar amb els serveis de Google Play." + "Compte no vàlid" + "El compte especificat no existeix en aquest dispositiu. Tria un compte diferent." + "Error desconegut relacionat amb els serveis de Google Play." + "Serveis de Google Play" + "El teu dispositiu no és compatible amb els serveis de Google Play, en què es basen les teves aplicacions. Per obtenir assistència, contacta amb el fabricant." + "Sembla que la data del dispositiu no és correcta. Comprova-la." + "Actualitza" + "Inicia sessió" + "Inicia sessió amb Google" + + "Una aplic. ha intentat utilitzar una versió errònia de serveis de Play." + "Una aplicació requereix que s\'activin els serveis de Google Play." + "Una aplicació requereix que s\'instal·lin els serveis de Google Play." + "Una aplicació requereix que s\'actualitzin els serveis de Google Play." + "Error dels serveis de Google Play" + "Sol·licitada per %1$s" + diff --git a/libs/google-play-services_lib/res/values-cs/strings.xml b/libs/google-play-services_lib/res/values-cs/strings.xml new file mode 100644 index 0000000..1b5423b --- /dev/null +++ b/libs/google-play-services_lib/res/values-cs/strings.xml @@ -0,0 +1,31 @@ + + + "Instalovat služby Google Play" + "Ke spuštění této aplikace jsou potřeba služby Google Play, které v telefonu nemáte." + "Ke spuštění této aplikace jsou potřeba služby Google Play, které v tabletu nemáte." + "Instalovat služby Google Play" + "Aktivovat služby Google Play" + "Ke spuštění této aplikace je třeba aktivovat služby Google Play." + "Aktivovat služby Google Play" + "Aktualizace služeb Google Play" + "Ke spuštění této aplikace je třeba aktualizovat služby Google Play." + "Chyba sítě" + "Připojení ke službám Google Play vyžaduje datové připojení." + "Neplatný účet" + "Zadaný účet v tomto zařízení neexistuje. Zvolte prosím jiný účet." + "Nastal neznámý problém se službami Google Play." + "Služby Google Play" + "Některé vaše aplikace vyžadují služby Google Play, které ve vašem zařízení nejsou podporovány. S žádostí o pomoc se prosím obraťte na výrobce." + "Datum v zařízení není správně nastaveno. Zkontrolujte prosím datum." + "Aktualizovat" + "Přihlásit se" + "Přihlásit se účtem Google" + + "Aplikace se pokusila použít nesprávnou verzi Služeb Google Play." + "Aplikace vyžaduje aktivované Služby Google Play." + "Aplikace vyžaduje instalaci Služeb Google Play." + "Aplikace vyžaduje aktualizaci Služeb Google Play." + "Chyba služeb Google Play" + "Požadováno aplikací %1$s" + diff --git a/libs/google-play-services_lib/res/values-da/strings.xml b/libs/google-play-services_lib/res/values-da/strings.xml new file mode 100644 index 0000000..daa2160 --- /dev/null +++ b/libs/google-play-services_lib/res/values-da/strings.xml @@ -0,0 +1,31 @@ + + + "Hent Google Play-tjenester" + "Denne app kan ikke køre uden Google Play-tjenester, som mangler på din telefon." + "Denne app kan ikke køre uden Google Play-tjenester, som mangler på din tablet." + "Hent Google Play-tjenester" + "Aktivér Google Play-tjenester" + "Denne app virker ikke, medmindre du aktiverer Google Play-tjenester." + "Aktivér Google Play-tjenester" + "Opdater Google Play-tjenester" + "Denne app kan ikke køre, medmindre du opdaterer Google Play-tjenester." + "Netværksfejl" + "Der kræves en dataforbindelse for at oprette forbindelse til Google Play-tjenester." + "Ugyldig konto" + "Den angivne konto findes ikke på denne enhed. Vælg en anden konto." + "Ukendt problem med Google Play-tjenester." + "Google Play-tjenester" + "Google Play-tjenester, som nogle af dine applikationer er afhængige af, understøttes ikke af din enhed. Kontakt producenten for at få hjælp." + "Datoen på enheden ser ud til at være forkert. Husk at kontrollere datoen på enheden." + "Opdater" + "Log ind" + "Log ind med Google" + + "En applikation forsøgte at bruge en defekt version af Google Play." + "En applikation kræver, at Google Play er aktiveret." + "En applikation kræver, at Google Play er installeret." + "En applikation kræver en opdatering af Google Play." + "Fejl i Google Play-tjenester" + "Anmodning fra %1$s" + diff --git a/libs/google-play-services_lib/res/values-de/strings.xml b/libs/google-play-services_lib/res/values-de/strings.xml new file mode 100644 index 0000000..ef6d779 --- /dev/null +++ b/libs/google-play-services_lib/res/values-de/strings.xml @@ -0,0 +1,31 @@ + + + "Google Play-Dienste installieren" + "Zur Nutzung dieser App sind Google Play-Dienste erforderlich, die auf Ihrem Telefon nicht installiert sind." + "Zur Nutzung dieser App sind Google Play-Dienste erforderlich, die auf Ihrem Tablet nicht installiert sind." + "Google Play-Dienste installieren" + "Google Play-Dienste aktivieren" + "Diese App funktioniert nur, wenn Sie die Google Play-Dienste aktivieren." + "Google Play-Dienste aktivieren" + "Google Play-Dienste aktualisieren" + "Diese App wird nur ausgeführt, wenn Sie die Google Play-Dienste aktualisieren." + "Netzwerkfehler" + "Um eine Verbindung zu den Google Play-Diensten herzustellen, ist eine Datenverbindung erforderlich." + "Ungültiges Konto" + "Das angegebene Konto ist auf diesem Gerät nicht vorhanden. Bitte wählen Sie ein anderes Konto aus." + "Unbekanntes Problem mit Google Play-Diensten" + "Google Play-Dienste" + "Google Play-Dienste, auf denen einige Ihrer Apps basieren, werden von diesem Gerät nicht unterstützt. Wenden Sie sich für weitere Informationen an den Hersteller." + "Das Datum auf dem Gerät scheint falsch zu sein. Bitte überprüfen Sie das Datum auf dem Gerät." + "Aktualisieren" + "Anmelden" + "Über Google anmelden" + + "Anwendung versuchte, defekte Google Play-Dienste-Version zu verwenden" + "Anwendung erfordert aktivierte Google Play-Dienste" + "Anwendung erfordert die Installation von Google Play-Diensten" + "Anwendung erfordert ein Update für Google Play-Dienste" + "Fehler bei Google Play-Diensten" + "Angefordert von %1$s" + diff --git a/libs/google-play-services_lib/res/values-el/strings.xml b/libs/google-play-services_lib/res/values-el/strings.xml new file mode 100644 index 0000000..13a5dc5 --- /dev/null +++ b/libs/google-play-services_lib/res/values-el/strings.xml @@ -0,0 +1,31 @@ + + + "Λήψη υπηρεσιών Google Play" + "Αυτή η εφαρμογή δεν θα εκτελεστεί χωρίς τις υπηρεσίες Google Play, οι οποίες λείπουν από το τηλέφωνό σας." + "Αυτή η εφαρμογή δεν θα εκτελεστεί χωρίς τις υπηρεσίες Google Play, οι οποίες λείπουν από το tablet σας." + "Λήψη υπηρεσιών Google Play" + "Ενεργοποίηση υπηρεσιών Google Play" + "Αυτή η εφαρμογή δεν θα λειτουργήσει εάν δεν έχετε ενεργοποιήσει τις υπηρεσίες Google Play." + "Ενεργοπ. υπηρεσιών Google Play" + "Ενημέρωση υπηρεσιών Google Play" + "Αυτή η εφαρμογή θα εκτελεστεί αφού ενημερώσετε τις υπηρεσίες Google Play." + "Σφάλμα δικτύου" + "Απαιτείται σύνδεση δεδομένων για να συνδεθείτε με τις Υπηρεσίες Google Play." + "Μη έγκυρος λογαριασμός" + "Ο συγκεκριμένος λογαριασμός δεν υπάρχει σε αυτήν τη συσκευή. Επιλέξτε έναν διαφορετικό λογαριασμό." + "Άγνωστο πρόβλημα με τις υπηρεσίες Google Play." + "Υπηρεσίες Google Play" + "Οι υπηρεσίες Google Play, στις οποίες βασίζονται ορισμένες από τις εφαρμογές σας, δεν υποστηρίζονται στη συσκευή σας. Επικοινωνήστε με τον κατασκευαστή για υποστήριξη." + "Η ημερομηνία στη συσκευή φαίνεται λανθασμένη. Ελέγξτε την ημερομηνία στη συσκευή." + "Ενημέρωση" + "Σύνδεση" + "Συνδεθείτε στο Google" + + "Απόπειρα χρήσης ακατάλληλης έκδοσης Υπηρεσιών Google Play από εφαρμογή" + "Μια εφαρμογή απαιτεί τις Υπηρεσίες Google Play για ενεργοποίηση." + "Μια εφαρμογή απαιτεί την εγκατάσταση των Υπηρεσιών Google Play." + "Μια εφαρμογή απαιτεί μια ενημέρωση για τις Υπηρεσίες Google Play." + "Σφάλμα υπηρεσιών Google Play" + "Υποβλήθηκε αίτημα από την εφαρμογή %1$s" + diff --git a/libs/google-play-services_lib/res/values-en-rGB/strings.xml b/libs/google-play-services_lib/res/values-en-rGB/strings.xml new file mode 100644 index 0000000..106d390 --- /dev/null +++ b/libs/google-play-services_lib/res/values-en-rGB/strings.xml @@ -0,0 +1,31 @@ + + + "Get Google Play services" + "This app won\'t run without Google Play services, which are missing from your phone." + "This app won\'t run without Google Play services, which are missing from your tablet." + "Get Google Play services" + "Enable Google Play services" + "This app won\'t work unless you enable Google Play services." + "Enable Google Play services" + "Update Google Play services" + "This app won\'t run unless you update Google Play services." + "Network Error" + "A data connection is required to connect to Google Play services." + "Invalid Account" + "The specified account does not exist on this device. Please choose a different account." + "Unknown issue with Google Play services." + "Google Play services" + "Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance." + "The date on the device appears to be incorrect. Please check the date on the device." + "Update" + "Sign in" + "Sign in with Google" + + "An application attempted to use a bad version of Google Play Services." + "An application requires Google Play Services to be enabled." + "An application requires installation of Google Play Services." + "An application requires an update for Google Play Services." + "Google Play services error" + "Requested by %1$s" + diff --git a/libs/google-play-services_lib/res/values-en-rIN/strings.xml b/libs/google-play-services_lib/res/values-en-rIN/strings.xml new file mode 100644 index 0000000..106d390 --- /dev/null +++ b/libs/google-play-services_lib/res/values-en-rIN/strings.xml @@ -0,0 +1,31 @@ + + + "Get Google Play services" + "This app won\'t run without Google Play services, which are missing from your phone." + "This app won\'t run without Google Play services, which are missing from your tablet." + "Get Google Play services" + "Enable Google Play services" + "This app won\'t work unless you enable Google Play services." + "Enable Google Play services" + "Update Google Play services" + "This app won\'t run unless you update Google Play services." + "Network Error" + "A data connection is required to connect to Google Play services." + "Invalid Account" + "The specified account does not exist on this device. Please choose a different account." + "Unknown issue with Google Play services." + "Google Play services" + "Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance." + "The date on the device appears to be incorrect. Please check the date on the device." + "Update" + "Sign in" + "Sign in with Google" + + "An application attempted to use a bad version of Google Play Services." + "An application requires Google Play Services to be enabled." + "An application requires installation of Google Play Services." + "An application requires an update for Google Play Services." + "Google Play services error" + "Requested by %1$s" + diff --git a/libs/google-play-services_lib/res/values-es-rUS/strings.xml b/libs/google-play-services_lib/res/values-es-rUS/strings.xml new file mode 100644 index 0000000..6be9059 --- /dev/null +++ b/libs/google-play-services_lib/res/values-es-rUS/strings.xml @@ -0,0 +1,31 @@ + + + "Obtener Google Play Services" + "Esta aplicación no se ejecutará si no instalasGoogle Play Services en tu dispositivo." + "Esta aplicación no se ejecutará si no instalas Google Play Services en tu tablet." + "Descargar Google Play Services" + "Activar Google Play Services" + "Esta aplicación no funcionará si no activas Google Play Services." + "Activar Google Play Services" + "Actualizar Google Play Services" + "Esta aplicación no se ejecutará si no actualizas Google Play Services." + "Error de red" + "Se necesita una conexión de datos para establecer conexión con Google Play Services." + "Cuenta no válida" + "La cuenta especificada no existe en este dispositivo. Elige otra cuenta." + "Error desconocido relacionado con Google Play Services" + "Google Play Services" + "Google Play Services, del cual dependen algunas de tus aplicaciones, no es compatible con tu dispositivo. Comunícate con el fabricante para obtener ayuda." + "Parece que la fecha del dispositivo es incorrecta. ¿Puedes revisarla?" + "Actualizar" + "Acceder" + "Acceder con Google" + + "Una aplic. intentó usar una versión no válida de Google Play Services" + "Una aplicación requiere que se active Google Play Services" + "Una aplicación requiere que se instale Google Play Services" + "Una aplicación requiere que se actualice Google Play Services" + "Error de Google Play Services" + "Solicitada por %1$s" + diff --git a/libs/google-play-services_lib/res/values-es/strings.xml b/libs/google-play-services_lib/res/values-es/strings.xml new file mode 100644 index 0000000..ed32995 --- /dev/null +++ b/libs/google-play-services_lib/res/values-es/strings.xml @@ -0,0 +1,31 @@ + + + "Descargar servicios de Google Play" + "Esta aplicación no se ejecutará si tu teléfono no tiene instalados los servicios de Google Play." + "Esta aplicación no se ejecutará si tu tablet no tiene instalados los servicios de Google Play." + "Descargar servicios de Google Play" + "Habilitar servicios de Google Play" + "Esta aplicación no funcionará si no habilitas los servicios de Google Play." + "Habilitar servicios de Google Play" + "Actualizar servicios de Google Play" + "Esta aplicación no se ejecutará si no actualizas los servicios de Google Play." + "Error de red" + "Se necesita una conexión de datos para establecer conexión con los servicios de Google Play." + "Cuenta no válida" + "La cuenta especificada no existe en este dispositivo. Selecciona otra cuenta." + "Error desconocido relacionado con los servicios de Google Play" + "Servicios de Google Play" + "Tu dispositivo no es compatible con los servicios de Google Play, de los cuales dependen tus aplicaciones. Para obtener asistencia, ponte en contacto el fabricante." + "Parece que la fecha del dispositivo es incorrecta. Compruébala." + "Actualizar" + "Iniciar sesión" + "Iniciar sesión con Google" + + "Una aplicación intentó usar versión incorrecta de servicios de Google Play." + "Una aplicación requiere que se habiliten los servicios de Play." + "Una aplicación requiere que se instalen los servicios de Google Play." + "Una aplicación requiere que se actualicen los servicios de Google Play." + "Error de los servicios de Google Play" + "Solicitada por %1$s" + diff --git a/libs/google-play-services_lib/res/values-et-rEE/strings.xml b/libs/google-play-services_lib/res/values-et-rEE/strings.xml new file mode 100644 index 0000000..281caff --- /dev/null +++ b/libs/google-play-services_lib/res/values-et-rEE/strings.xml @@ -0,0 +1,31 @@ + + + "Hankige Google Play teenused" + "Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie telefonis pole." + "Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie tahvelarvutis pole." + "Hankige Google Play teenused" + "Lubage Google Play teenused" + "See rakendus ei tööta, kui te ei luba Google Play teenuseid." + "Lubage Google Play teenused" + "Värskendage Google Play teenuseid" + "Seda rakendust ei saa käitada, kui te ei värskenda Google Play teenuseid." + "Võrgu viga" + "Google Play teenustega ühenduse loomiseks on vajalik andmesideühendus." + "Vale konto" + "Määratud kontot pole selles seadmes olemas. Valige muu konto." + "Google Play teenuste tundmatu probleem." + "Google Play teenused" + "Teie seade ei toeta Google Play teenuseid, millele mõni teie rakendustest toetub. Abi saamiseks võtke ühendust tootjaga." + "Seadme kuupäev paistab olevat vale. Kontrollige seadme kuupäeva." + "Värskenda" + "Logi sisse" + "Logi sisse Google\'iga" + + "Rakendus püüdis kasutada Google Play teenuste sobimatut versiooni." + "Rakenduse kasutamiseks peavad olema lubatud Google Play teenused." + "Rakenduse kasutamiseks peavad olema installitud Google Play teenused." + "Rakenduse kasutamiseks tuleb värskendada Google Play teenuseid." + "Viga Google Play teenustes" + "Päringu esitas: %1$s" + diff --git a/libs/google-play-services_lib/res/values-et/strings.xml b/libs/google-play-services_lib/res/values-et/strings.xml new file mode 100644 index 0000000..281caff --- /dev/null +++ b/libs/google-play-services_lib/res/values-et/strings.xml @@ -0,0 +1,31 @@ + + + "Hankige Google Play teenused" + "Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie telefonis pole." + "Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie tahvelarvutis pole." + "Hankige Google Play teenused" + "Lubage Google Play teenused" + "See rakendus ei tööta, kui te ei luba Google Play teenuseid." + "Lubage Google Play teenused" + "Värskendage Google Play teenuseid" + "Seda rakendust ei saa käitada, kui te ei värskenda Google Play teenuseid." + "Võrgu viga" + "Google Play teenustega ühenduse loomiseks on vajalik andmesideühendus." + "Vale konto" + "Määratud kontot pole selles seadmes olemas. Valige muu konto." + "Google Play teenuste tundmatu probleem." + "Google Play teenused" + "Teie seade ei toeta Google Play teenuseid, millele mõni teie rakendustest toetub. Abi saamiseks võtke ühendust tootjaga." + "Seadme kuupäev paistab olevat vale. Kontrollige seadme kuupäeva." + "Värskenda" + "Logi sisse" + "Logi sisse Google\'iga" + + "Rakendus püüdis kasutada Google Play teenuste sobimatut versiooni." + "Rakenduse kasutamiseks peavad olema lubatud Google Play teenused." + "Rakenduse kasutamiseks peavad olema installitud Google Play teenused." + "Rakenduse kasutamiseks tuleb värskendada Google Play teenuseid." + "Viga Google Play teenustes" + "Päringu esitas: %1$s" + diff --git a/libs/google-play-services_lib/res/values-fa/strings.xml b/libs/google-play-services_lib/res/values-fa/strings.xml new file mode 100644 index 0000000..4546e57 --- /dev/null +++ b/libs/google-play-services_lib/res/values-fa/strings.xml @@ -0,0 +1,31 @@ + + + "دریافت خدمات Google Play" + "این برنامه بدون خدمات Google Play اجرا نمی‌شود، این خدمات در تلفن شما وجود ندارد." + "این برنامه بدون خدمات Google Play اجرا نمی‌شود، این خدمات در رایانهٔ لوحی شما وجود ندارد." + "دریافت خدمات Google Play" + "فعال کردن خدمات Google Play" + "تا زمانی‌که خدمات Google Play را فعال نکنید این برنامه کار نمی‌کند." + "فعال کردن خدمات Google Play" + "به‌روزرسانی خدمات Google Play" + "تا زمانی‌که خدمات Google Play را به‌روز نکنید این برنامه کار نمی‌کند." + "خطای شبکه" + "برای اتصال به خدمات Google Play اتصال داده لازم است." + "حساب نامعتبر" + "حسابی که تعیین کردید در این دستگاه وجود ندارد. لطفاً حساب دیگری را انتخاب کنید." + "مشکل نامشخص در خدمات Google Play." + "خدمات Google Play" + "خدمات Google Play، که برخی از برنامه‌های شما به آن وابسته است، توسط دستگاه شما پشتیبانی نمی‌شود. لطفاً برای دریافت کمک با سازنده تماس بگیرید." + "تاریخ روی دستگاه ظاهراً اشتباه است. لطفاً تاریخ روی دستگاه را بررسی کنید." + "به‌روزرسانی" + "ورود به سیستم" + "ورود به سیستم با Google‎" + + "برنامه‌ای تلاش کرد از نسخه نادرستی از خدمات Google Play استفاده کند." + "برنامه‌ای به فعال کردن خدمات Google Play نیاز دارد." + "برنامه‌ای به نصب خدمات Google Play نیاز دارد." + "برنامه‌ای به به‌روزرسانی خدمات Google Play نیاز دارد." + "خطا در خدمات Google Play" + "درخواست توسط %1$s" + diff --git a/libs/google-play-services_lib/res/values-fi/strings.xml b/libs/google-play-services_lib/res/values-fi/strings.xml new file mode 100644 index 0000000..00d3ceb --- /dev/null +++ b/libs/google-play-services_lib/res/values-fi/strings.xml @@ -0,0 +1,31 @@ + + + "Asenna Google Play -palvelut" + "Tämä sovellus ei toimi ilman Google Play -palveluita, jotka puuttuvat puhelimesta." + "Tämä sovellus ei toimi ilman Google Play -palveluita, jotka puuttuvat tablet-laitteesta." + "Asenna Google Play -palvelut" + "Ota Google Play -palvelut käyttöön" + "Tämä sovellus ei toimi, ellet ota Google Play -palveluita käyttöön." + "Ota Google Play -palv. käyttöön" + "Päivitä Google Play -palvelut" + "Tämä sovellus ei toimi, ellet päivitä Google Play -palveluita." + "Verkkovirhe" + "Google Play -palveluiden käyttöön tarvitaan tietoliikenneyhteys." + "Tili ei kelpaa" + "Kyseistä tiliä ei ole tällä laitteella. Valitse toinen tili." + "Tuntematon ongelma käytettäessä Google Play -palveluita." + "Google Play -palvelut" + "Google Play -palveluita, joita osa sovelluksistasi käyttää, ei tueta laitteellasi. Pyydä ohjeita laitteen valmistajalta." + "Laitteen päivämäärä vaikuttaa virheelliseltä. Tarkista laitteen päivämäärä." + "Päivitä" + "Kirjaudu" + "Kirjaudu Google-tiliin" + + "Sovellus yritti käyttää virheellistä Google Play -palveluiden versiota" + "Ota käyttöön Google Play -palvelut, jotta sovellus toimii." + "Asenna Google Play -palvelut, jotta sovellus toimii." + "Päivitä Google Play -palvelut, jotta sovellus toimii." + "Virhe Google Play -palveluissa" + "Pyynnön teki %1$s" + diff --git a/libs/google-play-services_lib/res/values-fr-rCA/strings.xml b/libs/google-play-services_lib/res/values-fr-rCA/strings.xml new file mode 100644 index 0000000..e915fe4 --- /dev/null +++ b/libs/google-play-services_lib/res/values-fr-rCA/strings.xml @@ -0,0 +1,31 @@ + + + "Installer les services Google Play" + "Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre téléphone." + "Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre tablette." + "Installer les services Google Play" + "Activer les services Google Play" + "Cette application ne fonctionnera pas tant que vous n\'aurez pas activé les services Google Play." + "Activer les services Google Play" + "Mettre à jour les services Google Play" + "Cette application ne fonctionnera pas tant que vous n\'aurez pas mis à jour les services Google Play." + "Erreur réseau" + "Vous devez disposer d\'une connexion de données pour utiliser les services Google Play." + "Compte erroné" + "Le compte indiqué n\'existe pas sur cet appareil. Veuillez sélectionner un autre compte." + "Problème inconnu avec les services Google Play." + "Services Google Play" + "Les services Google Play, dont dépendent certaines de vos applications, ne sont pas compatibles avec votre appareil. Veuillez contacter le fabricant pour obtenir de l\'aide." + "La date sur l\'appareil semble incorrecte. Veuillez la vérifier." + "Mettre à jour" + "Connexion" + "Se connecter via Google" + + "Une application requiert une version valide des services Google Play" + "Une application requiert l\'activation des services Google Play" + "Une application requiert l\'installation des services Google Play" + "Une application requiert la mise à jour des services Google Play" + "Erreur liée aux services Google Play" + "Demandée par %1$s" + diff --git a/libs/google-play-services_lib/res/values-fr/strings.xml b/libs/google-play-services_lib/res/values-fr/strings.xml new file mode 100644 index 0000000..321b283 --- /dev/null +++ b/libs/google-play-services_lib/res/values-fr/strings.xml @@ -0,0 +1,31 @@ + + + "Installer les services Google Play" + "Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre téléphone." + "Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre tablette." + "Installer services Google Play" + "Activer les services Google Play" + "Cette application ne fonctionnera pas tant que vous n\'aurez pas activé les services Google Play." + "Activer services Google Play" + "Mettre à jour les services Google Play" + "Cette application ne fonctionnera pas tant que vous n\'aurez pas mis à jour les services Google Play." + "Erreur réseau" + "Vous devez disposer d\'une connexion de données pour utiliser les services Google Play." + "Compte erroné" + "Le compte indiqué n\'existe pas sur cet appareil. Veuillez sélectionner un autre compte." + "Problème inconnu avec les services Google Play." + "Services Google Play" + "Les services Google Play, dont dépendent certaines de vos applications, ne sont pas compatibles avec votre appareil. Veuillez contacter le fabricant pour obtenir de l\'aide." + "La date sur l\'appareil semble incorrecte. Veuillez la vérifier." + "Mettre à jour" + "Connexion" + "Se connecter avec Google" + + "Une application requiert une version valide des services Google Play" + "Une application requiert l\'activation des services Google Play" + "Une application requiert l\'installation des services Google Play" + "Une application requiert la mise à jour des services Google Play" + "Erreur liée aux services Google Play" + "Demandée par %1$s" + diff --git a/libs/google-play-services_lib/res/values-hi/strings.xml b/libs/google-play-services_lib/res/values-hi/strings.xml new file mode 100644 index 0000000..e1b3b95 --- /dev/null +++ b/libs/google-play-services_lib/res/values-hi/strings.xml @@ -0,0 +1,31 @@ + + + "Google Play सेवाएं पाएं" + "यह एप्स Google Play सेवाओं के बिना नहीं चलेगा, जो आपके फ़ोन में नहीं हैं." + "यह एप्स Google Play सेवाओं के बिना नहीं चलेगा, जो आपके टेबलेट में नहीं हैं." + "Google Play सेवाएं पाएं" + "Google Play सेवाएं सक्षम करें" + "जब तक आप Google Play सेवाएं सक्षम नहीं करते, तब तक यह एप्स कार्य नहीं करेगा." + "Google Play सेवाएं सक्षम करें" + "Google Play सेवाएं से नई जानकारी" + "जब तक आप Google Play सेवाओं से नई जानकारी नहीं लेते हैं, तब तक यह एप्स नहीं चलेगा." + "नेटवर्क त्रुटि" + "Google Play सेवाओं से कनेक्ट करने के लिए डेटा कनेक्शन की आवश्यकता है." + "अमान्य खाता" + "निर्दिष्ट खाता इस उपकरण पर मौजूद नहीं है. कृपया कोई भिन्न खाता चुनें." + "Google Play सेवाओं के साथ अज्ञात समस्या." + "Google Play सेवाएं" + "Google Play सेवाएं, जिन पर आपके कुछ एप्स निर्भर करते हैं, आपके उपकरण द्वारा समर्थित नहीं हैं. कृपया सहायता के लिए निर्माता से संपर्क करें." + "उपकरण का दिनांक गलत प्रतीत हो रहा है. कृपया उपकरण का दिनांक जांचें." + "नई जानकारी पाएं" + "प्रवेश करें" + "Google से प्रवेश करें" + + "एप्लि. ने Google Play सेवाओं के खराब संस्करण के उपयोग का प्रयास किया." + "एप्स के लिए Google Play सेवाओं को सक्षम किए जाने की आवश्यकता है." + "एप्स के लिए Google Play सेवाओं के इंस्टॉलेशन की आवश्यकता है." + "एप्स के लिए Google Play सेवाओं में Google Play से नई जानकारी की आवश्यकता है." + "Google Play सेवाएं त्रुटि" + "%1$s द्वारा अनुरोधित" + diff --git a/libs/google-play-services_lib/res/values-hr/strings.xml b/libs/google-play-services_lib/res/values-hr/strings.xml new file mode 100644 index 0000000..b7d462d --- /dev/null +++ b/libs/google-play-services_lib/res/values-hr/strings.xml @@ -0,0 +1,31 @@ + + + "Preuzmi usluge za Google Play" + "Ova aplikacija neće funkcionirati bez usluga za Google Play, koje nisu instalirane na vašem telefonu." + "Ova aplikacija neće funkcionirati bez usluga za Google Play, koje nisu instalirane na vašem tabletnom računalu." + "Preuzmi usluge za Google Play" + "Omogući usluge za Google Play" + "Ova aplikacija neće raditi ako ne omogućite usluge za Google Play." + "Omogući usluge za Google Play" + "Ažuriraj usluge za Google Play" + "Ova se aplikacija neće pokrenuti ako ne ažurirate usluge za Google Play." + "Mrežna pogreška" + "Potrebna je podatkovna veza za povezivanje s uslugama Google Play." + "Nevažeći račun" + "Navedeni račun ne postoji na ovom uređaju. Odaberite neki drugi račun." + "Nepoznata poteškoća s uslugama za Google Play." + "Usluge za Google Play" + "Usluge za Google Play, koje su potrebne za funkcioniranje nekih vaših aplikacija, nisu podržane na vašem uređaju. Pomoć potražite od proizvođača." + "Čini se da datum na uređaju nije točan. Provjerite datum na uređaju." + "Ažuriranje" + "Prijava" + "Prijava uslugom Google" + + "Aplikacija je pokušala upotrijebiti lošu verziju Usluga za Google Play." + "Aplikacija zahtijeva omogućavanje Usluga za Google Play." + "Aplikacija zahtijeva instaliranje Usluga za Google Play." + "Aplikacija zahtijeva ažuriranje Usluga za Google Play." + "Pogreška usluga za Google Play" + "Zahtijeva aplikacija %1$s" + diff --git a/libs/google-play-services_lib/res/values-hu/strings.xml b/libs/google-play-services_lib/res/values-hu/strings.xml new file mode 100644 index 0000000..cd15ad3 --- /dev/null +++ b/libs/google-play-services_lib/res/values-hu/strings.xml @@ -0,0 +1,31 @@ + + + "Play Szolgáltatások telepítése" + "Az alkalmazás működéséhez a Google Play Szolgáltatások szükségesek, ezek nincsenek telepítve a telefonon." + "Az alkalmazás működéséhez a Google Play Szolgáltatások szükségesek, ezek nincsenek telepítve a táblagépen." + "Play Szolgáltatások telepítése" + "Google Play Szolgáltatások aktiválása" + "Az alkalmazás csak akkor fog működni, ha engedélyezi a Google Play Szolgáltatásokat." + "Play Szolgáltatások aktiválása" + "Play Szolgáltatások frissítése" + "Az alkalmazás csak akkor fog működni, ha frissíti a Google Play Szolgáltatásokat." + "Hálózati hiba" + "A Google Play Szolgáltatásokhoz történő kapcsolódáshoz adatkapcsolat szükséges." + "Érvénytelen fiók" + "A megadott fiók nem létezik ezen az eszközön. Kérjük, válasszon másik fiókot." + "Ismeretlen hiba a Google Play Szolgáltatásokban." + "Google Play Szolgáltatások" + "A Google Play Szolgáltatásokat, amelyre egyes alkalmazások támaszkodnak, nem támogatja az eszköz. Segítségért forduljon az eszköz gyártójához." + "Az eszközön beállított dátum helytelen. Kérjük, ellenőrizze azt." + "Frissítés" + "Belépés" + "Google-bejelentkezés" + + "Egy alkalmazás a Play Szolgáltatások rossz verzióját akarta használni." + "Egy alkalmazás kéri a Google Play Szolgáltatások engedélyezését." + "Egy alkalmazás kéri a Google Play Szolgáltatások telepítését." + "Egy alkalmazás kéri a Google Play Szolgáltatások frissítését." + "Google Play szolgáltatási hiba" + "Igénylő: %1$s" + diff --git a/libs/google-play-services_lib/res/values-hy-rAM/strings.xml b/libs/google-play-services_lib/res/values-hy-rAM/strings.xml new file mode 100644 index 0000000..d89be9b --- /dev/null +++ b/libs/google-play-services_lib/res/values-hy-rAM/strings.xml @@ -0,0 +1,31 @@ + + + "Տեղադրեք Google Play ծառայությունները" + "Այս հավելվածը չի գործարկվի առանց Google Play ծառայությունների, որոնք բացակայում են ձեր հեռախոսում:" + "Այս հավելվածը չի գործարկվի առանց Google Play ծառայությունների, որոնք բացակայում են ձեր գրասալիկում:" + "Տեղադրել Google Play ծառայությունները" + "Միացնել Google Play ծառայությունները" + "Այս ծրագիրը չի աշխատի, եթե դուք չմիացնեք Google Play ծառայությունները:" + "Միացնել Google Play ծառայությունները" + "Նորացրեք Google Play ծառայությունները" + "Այս ծրագիրը չի գործարկվի, եթե դուք չնորացնեք Google Play ծառայությունները:" + "Ցանցի սխալ կա" + "Պահանջվում է տվյալների կապ` Google Play ծառայություններին միանալու համար:" + "Հաշիվն անվավեր է" + "Նշված հաշիվը գոյություն չունի այս սարքում: Ընտրեք այլ հաշիվ:" + "Անհայտ խնդիր՝ Google Play ծառայություններում:" + "Google Play ծառայություններ" + "Google Play ծառայությունները, որոնց ապավինում են ձեր ծրագրերից որոշները, չեն աջակցվում ձեր սարքի կողմից: Խնդրում ենք կապվել արտադրողի հետ օգնության համար:" + "Սարքի ամսաթիվը կարծես սխալ է: Ստուգեք սարքի ամսաթիվը:" + "Նորացնել" + "Մուտք գործել" + "Մուտք գործեք Google-ով" + + "Հավելվածը փորձել է կիրառել Google Play ծառայությունների վատ տարբերակը:" + "Հավելվածը պահանջում է միացնել Google Play ծառայությունները:" + "Հավելվածը պահանջում է տեղադրել Google Play ծառայությունները:" + "Հավելվածը պահանջում է թարմացնել Google Play ծառայությունները:" + "Google Play ծառայությունների սխալ" + "%1$s-ի հարցմամբ" + diff --git a/libs/google-play-services_lib/res/values-in/strings.xml b/libs/google-play-services_lib/res/values-in/strings.xml new file mode 100644 index 0000000..526b84a --- /dev/null +++ b/libs/google-play-services_lib/res/values-in/strings.xml @@ -0,0 +1,31 @@ + + + "Dapatkan layanan Google Play" + "Aplikasi ini tidak akan berjalan tanpa layanan Google Play, yang tidak ada di ponsel Anda." + "Aplikasi ini tidak akan berjalan tanpa layanan Google Play, yang tidak ada di tablet Anda." + "Dapatkan layanan Google Play" + "Aktifkan layanan Google Play" + "Aplikasi ini tidak akan bekerja sampai Anda mengaktifkan layanan Google Play." + "Aktifkan layanan Google Play" + "Perbarui layanan Google Play" + "Aplikasi ini tidak akan berjalan sampai Anda memperbarui layanan Google Play." + "Kesalahan Jaringan" + "Sambungan data diperlukan untuk tersambung ke layanan Google Play." + "Akun Tidak Valid" + "Akun yang ditentukan tidak ada di perangkat ini. Pilih akun lain." + "Masalah tidak diketahui pada layanan Google Play." + "Layanan Google Play" + "Layanan Google Play, yang diandalkan oleh beberapa aplikasi Anda, tidak didukung oleh perangkat Anda. Hubungi pabrikan untuk mendapatkan bantuan." + "Tampaknya tanggal di perangkat salah. Periksa tanggal di perangkat." + "Perbarui" + "Masuk" + "Masuk dengan Google" + + "Aplikasi mencoba menggunakan versi Layanan Google Play yang rusak." + "Aplikasi membutuhkan Layanan Google Play untuk dapat diaktifkan." + "Aplikasi membutuhkan pemasangan Layanan Google Play." + "Aplikasi membutuhkan pembaruan untuk Layanan Google Play." + "Kesalahan layanan Google Play" + "Diminta oleh %1$s" + diff --git a/libs/google-play-services_lib/res/values-it/strings.xml b/libs/google-play-services_lib/res/values-it/strings.xml new file mode 100644 index 0000000..f3c9f1f --- /dev/null +++ b/libs/google-play-services_lib/res/values-it/strings.xml @@ -0,0 +1,31 @@ + + + "Installa Google Play Services" + "L\'app non funzionerà senza Google Play Services, non presente sul tuo telefono." + "L\'app non funzionerà senza Google Play Services, non presente sul tuo tablet." + "Installa Google Play Services" + "Attiva Google Play Services" + "L\'app non funzionerà se non attivi Google Play Services." + "Attiva Google Play Services" + "Aggiorna Google Play Services" + "L\'app non funzionerà se non aggiorni Google Play Services." + "Errore di rete" + "È necessaria una connessione dati per connettersi a Google Play Services." + "Account non valido" + "L\'account specificato non esiste su questo dispositivo. Scegli un altro account." + "Problema sconosciuto con Google Play Services." + "Google Play Services" + "La piattaforma Google Play Services, su cui sono basate alcune delle tue applicazioni, non è supportata dal dispositivo in uso. Per assistenza, contatta il produttore." + "La data sul dispositivo sembra sbagliata. Controllala." + "Aggiorna" + "Accedi" + "Accedi con Google" + + "Un\'app ha tentato di usare una versione non valida di Play Services." + "Un\'applicazione richiede l\'attivazione di Google Play Services." + "Un\'applicazione richiede l\'installazione di Google Play Services." + "Un\'applicazione richiede un aggiornamento di Google Play Services." + "Errore Google Play Services" + "Richiesta da %1$s" + diff --git a/libs/google-play-services_lib/res/values-iw/strings.xml b/libs/google-play-services_lib/res/values-iw/strings.xml new file mode 100644 index 0000000..76869a9 --- /dev/null +++ b/libs/google-play-services_lib/res/values-iw/strings.xml @@ -0,0 +1,31 @@ + + + "קבל את שירותי Google Play" + "אפליקציה זו לא תפעל ללא שירותי Google Play, החסרים בטלפון שלך." + "אפליקציה זו לא תפעל ללא שירותי Google Play, החסרים בטאבלט שלך." + "קבל את שירותי Google Play" + "הפעלת שירותי Google Play" + "אפליקציה זו לא תעבוד אם לא תפעיל את שירותי Google Play." + "הפעל את שירותי Google Play" + "עדכון שירותי Google Play" + "אפליקציה זו לא תפעל אם לא תעדכן את שירותי Google Play." + "שגיאת רשת." + "דרוש חיבור נתונים כדי להתחבר לשירותי Google Play." + "חשבון לא חוקי" + "החשבון שצוין לא קיים במכשיר זה. בחר חשבון אחר." + "בעיה לא ידועה בשירותי Google Play." + "שירותי Google Play" + "שירותי Google Play, שחלק מהאפליקציות שלך מתבססות עליהם, אינם נתמכים על ידי המכשיר שברשותך. צור קשר עם היצרן לקבלת סיוע." + "נראה שהתאריך במכשיר שגוי. בדוק את התאריך במכשיר." + "עדכן" + "היכנס" + "היכנס באמצעות Google" + + "יש אפליקציה שניסתה להשתמש בגרסה שגויה של שירותי Google Play." + "יש אפליקציה המחייבת הפעלה של שירותי Google Play." + "יש אפליקציה המחייבת התקנה של שירותי Google Play." + "יש אפליקציה המחייבת עדכון של שירותי Google Play." + "שגיאה בשירותי Google Play" + "התבקשה על ידי %1$s" + diff --git a/libs/google-play-services_lib/res/values-ja/strings.xml b/libs/google-play-services_lib/res/values-ja/strings.xml new file mode 100644 index 0000000..0d8b606 --- /dev/null +++ b/libs/google-play-services_lib/res/values-ja/strings.xml @@ -0,0 +1,31 @@ + + + "Play開発者サービスの入手" + "このアプリの実行にはGoogle Play開発者サービスが必要ですが、お使いの携帯端末にはインストールされていません。" + "このアプリの実行にはGoogle Play開発者サービスが必要ですが、お使いのタブレットにはインストールされていません。" + "Play開発者サービスの入手" + "Play開発者サービスの有効化" + "このアプリの実行には、Google Play開発者サービスの有効化が必要です。" + "Play開発者サービスの有効化" + "Play開発者サービスの更新" + "このアプリの実行には、Google Play開発者サービスの更新が必要です。" + "ネットワークエラー" + "Google Play開発者サービスに接続するには、データ接続が必要です。" + "無効なアカウント" + "指定したアカウントはこの端末上に存在しません。別のアカウントを選択してください。" + "Google Play開発者サービスで原因不明の問題が発生しました。" + "Google Play開発者サービス" + "一部のアプリが使用しているGoogle Play開発者サービスは、お使いの端末ではサポートされていません。詳しくは、端末メーカーまでお問い合わせください。" + "端末上の日付が正しくないようです。端末上の日付をご確認ください。" + "更新" + "ログイン" + "Googleでログイン" + + "アプリはGoogle Play開発者サービスの不適切なバージョンを使用しようとしました。" + "アプリではGoogle Play開発者サービスを有効にする必要があります。" + "アプリではGoogle Play開発者サービスをインストールする必要があります。" + "アプリではGoogle Play開発者サービスをアップデートする必要があります。" + "Google Play開発者サービスのエラー" + "%1$sによるリクエスト" + diff --git a/libs/google-play-services_lib/res/values-ka-rGE/strings.xml b/libs/google-play-services_lib/res/values-ka-rGE/strings.xml new file mode 100644 index 0000000..8a2c74a --- /dev/null +++ b/libs/google-play-services_lib/res/values-ka-rGE/strings.xml @@ -0,0 +1,31 @@ + + + "Google Play სერვისების მიღება" + "ეს აპი ვერ გაეშვება Google Play სერვისების გარეშე, რაც თქვენს ტელეფონზე ვერ იძებნება." + "ეს აპი ვერ გაეშვება Google Play სერვისების გარეშე, რაც თქვენს ტელეფონზე ვერ იძებნება." + "Google Play სერვისების მიღება" + "Google Play სერვისების გააქტიურება" + "ეს აპი არ იმუშავებს, თუ არ გაააქტიურებთ Google Play სერვისებს." + "Google Play სერვისების გააქტიურება" + "Google Play სერვისების განახლება" + "ეს აპი ვერ გაეშვება, თუ Google Play სერვისებს არ განაახლებთ." + "ქსელის შეცდომა" + "Google Play Services-თან დასაკავშირებლად მონაცემთა გადაცემა აუცილებელია." + "ანგარიში არასწორია" + "მითითებული ანგარიში ამ მოწყობილობაზე არ არსებობს. გთხოვთ, აირჩიოთ სხვა ანგარიში." + "Google Play სერვისებთან დაკავშირებით უცნობი შეფერხება წარმოიშვა." + "Google Play სერვისები" + "Google Play სერვისები, რაც თქვენს ზოგიერთ აპს ჭირდება, თქვენს მოწყობილობაზე მხარდაჭერილი არ არის. გთხოვთ, დაუკავშირდეთ მწარმოებელს დახმარებისათვის." + "როგორც ჩანს, მოწყობილობის თარიღი არასწორია. გთხოვთ, შეამოწმოთ მოწყობილობის თარიღი." + "განახლება" + "შესვლა" + "Google-ით შესვლა" + + "აპლიკაცია შეეცადა გამოეყენებინა Google Play სერვისების არასწორი ვერსია." + "აპლიკაცია საჭიროებს გააქტიურებულ Google Play Services." + "აპლიკაცია საჭიროებს Google Play Services-ის ინსტალაციას." + "აპლიკაცია საჭიროებს Google Play Services-ის განახლებას." + "Google Play სერვისების შეცდომა" + "მომთხოვნი: %1$s" + diff --git a/libs/google-play-services_lib/res/values-km-rKH/strings.xml b/libs/google-play-services_lib/res/values-km-rKH/strings.xml new file mode 100644 index 0000000..afebf30 --- /dev/null +++ b/libs/google-play-services_lib/res/values-km-rKH/strings.xml @@ -0,0 +1,31 @@ + + + "ទទួល​សេវាកម្ម​កម្សាន្ត Google" + "កម្មវិធី​នេះ​នឹង​មិន​ដំណើរការ​​ទេ​បើ​គ្មាន​​សេវាកម្ម​កម្សាន្ត​ Google ដែល​ទូរស័ព្ទ​របស់​​អ្នក​មិន​មាន។" + "​​កម្មវិធី​នេះ​នឹង​មិន​ដំណើរការ​​ទេ​បើ​គ្មាន​​សេវាកម្ម​កម្សាន្ត​ Google ដែល​​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក​មិន​មាន។" + "ទទួល​សេវាកម្ម​កម្សាន្ត Google" + "បើក​សេវាកម្ម​កម្សាន្ត Google" + "កម្ម​វិធី​នេះ​នឹង​មិន​ដំណើរការ​ទេ​ លុះត្រាតែ​អ្នក​បើក​សេវាកម្ម​​កម្សាន្ត​ Google ។" + "បើក​សេវាកម្ម​កម្សាន្ត Google" + "ធ្វើ​បច្ចុប្បន្នភាព​សេវាកម្ម​កម្សាន្ត Google" + "កម្មវិធី​នេះ​នឹង​មិន​ដំណើរការ​ទេ​ លុះត្រាតែ​អ្នក​ធ្វើ​បច្ចុប្បន្នភាព​សេវាកម្ម​កម្សាន្ត Google ។" + "កំហុស​​បណ្ដាញ" + "បាន​ទាមទារ​ការ​តភ្ជាប់​ទិន្នន័យ ដើម្បី​ភ្ជាប់​សេវាកម្ម​ឃ្លាំង​កម្មវិធី។" + "គណនី​មិន​ត្រឹមត្រូវ" + "គណនី​ដែល​បាន​បញ្ជាក់​មិន​មាន​នៅ​លើ​ឧបករណ៍​នេះ​ទេ។ សូម​ជ្រើស​គណនី​ផ្សេង​។" + "មិន​ស្គាល់​បញ្ហា​ជាមួយ​សេវាកម្ម​កម្សាន្ត Google ។" + "សេវាកម្ម​កម្សាន្ត​ Google" + "សេវាកម្ម​កម្សាន្ត Google អាស្រ័យ​លើ​កម្មវិធី​របស់​អ្នក មិន​ត្រូវ​បាន​គាំទ្រ​ដោយ​ឧបករណ៍​របស់​អ្នក។ សូម​ទាក់ទង​ក្រុមហ៊ុន​ផលិត​សម្រាប់​ជំនួយ។" + "កាលបរិច្ឆេទ​លើ​ឧបករណ៍​បង្ហាញ​ថា​មិន​ត្រឹមត្រូវ។ សូម​ពិនិត្យ​កាលបរិច្ឆេទ​លើ​ឧបករណ៍។" + "ធ្វើ​បច្ចុប្បន្នភាព" + "ចូល" + "ចូល​ដោយ​ប្រើ​ Google" + + "កម្មវិធី​​​ព្យាយាម​ប្រើ​កំណែ​មិនល្អ​របស់​សេវា​កម្ម​ឃ្លាំ​កម្មវិធី។" + "កម្មវិធី​ទាមទារ​​បើក​សេវាកម្ម​ឃ្លាំង​កម្មវិធី។" + "កម្មវិធី​ទាមទារ​ការ​ដំឡើង​សេវាកម្ម​ឃ្លាំង​កម្មវិធី។" + "កម្មវិធី​ទាមទារ​​ធ្វើ​បច្ចុប្បន្នភាព​សេវាកម្ម​ឃ្លាំង​កម្មវិធី។" + "កំហុស​សេវា​កម្ម​កម្សាន្ត Google" + "បាន​ស្នើ​ដោយ %1$s" + diff --git a/libs/google-play-services_lib/res/values-ko/strings.xml b/libs/google-play-services_lib/res/values-ko/strings.xml new file mode 100644 index 0000000..e37f1fd --- /dev/null +++ b/libs/google-play-services_lib/res/values-ko/strings.xml @@ -0,0 +1,31 @@ + + + "Google Play 서비스 설치" + "휴대전화에 Google Play 서비스가 설치되어 있어야 이 앱이 실행됩니다." + "태블릿에 Google Play 서비스가 설치되어 있어야 이 앱이 실행됩니다." + "Google Play 서비스 설치" + "Google Play 서비스 사용" + "Google Play 서비스를 사용하도록 설정해야 이 앱이 작동합니다." + "Google Play 서비스 사용" + "Google Play 서비스 업데이트" + "Google Play 서비스를 업데이트해야만 이 앱이 실행됩니다." + "네트워크 오류" + "Google Play 서비스에 연결하려면 데이터 연결이 필요합니다." + "올바르지 않은 계정" + "지정한 계정이 이 기기에 존재하지 않습니다. 다른 계정을 선택하세요." + "Google Play 서비스에 알 수 없는 문제가 발생했습니다." + "Google Play 서비스" + "일부 사용자 애플리케이션에 필요한 Google Play 서비스가 사용자 기기에서 지원되지 않습니다. 기기 제조업체에 문의하시기 바랍니다." + "기기의 날짜가 잘못된 것 같습니다. 기기의 날짜를 확인해 주세요." + "업데이트" + "로그인" + "Google 계정으로 로그인" + + "애플리케이션에서 잘못된 버전의 Google Play 서비스를 사용하려고 했습니다." + "Google Play 서비스를 사용하도록 설정해야 하는 애플리케이션입니다." + "Google Play 서비스를 설치해야 하는 애플리케이션입니다." + "Google Play 서비스를 업데이트해야 하는 애플리케이션입니다." + "Google Play 서비스 오류" + "%1$s에서 요청" + diff --git a/libs/google-play-services_lib/res/values-lo-rLA/strings.xml b/libs/google-play-services_lib/res/values-lo-rLA/strings.xml new file mode 100644 index 0000000..32bcb0b --- /dev/null +++ b/libs/google-play-services_lib/res/values-lo-rLA/strings.xml @@ -0,0 +1,31 @@ + + + "ຕິດຕັ້ງບໍລິການ Google Play" + "ແອັບຯນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້ໂດຍທີ່ບໍ່ມີບໍລິການ Google Play ເຊິ່ງຂາດຫາຍໄປໃນໂທລະສັບຂອງທ່ານ." + "ແອັບຯນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້ໂດຍທີ່ບໍ່ມີບໍລິການ Google Play ເຊິ່ງຂາດຫາຍໄປໃນແທັບເລັດຂອງທ່ານ." + "ຕິດຕັ້ງບໍລິການ Google Play" + "ເປີດໃຊ້ບໍລິການ Google Play" + "ແອັບຯນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້ຈົນກວ່າທ່ານຈະເປີດໃຊ້ບໍລິການ Google Play" + "ເປີດໃຊ້ບໍລິການ Google Play" + "ອັບເດດບໍລິການ Google Play" + "ແອັບຯນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້ຈົນກວ່າທ່ານຈະອັບເດດບໍລິການ Google Play." + "ເຄືອຂ່າຍຜິດພາດ" + "ຕ້ອງໃຊ້ການເຊື່ອມຕໍ່ອິນເຕີເນັດເພື່ອໃຊ້ Google Play Services." + "ບັນຊີບໍ່ຖືກຕ້ອງ" + "ບັນຊີທີ່ເລືອກບໍ່ມີໃນອຸປະກອນນີ້. ກະລຸນາເລືອກບັນຊີອື່ນ." + "ມີປັນຫາທີ່ບໍ່ຄາດຄິດໃນບໍລິການ Google Play." + "ບໍລິການ Google Play" + "ບໍລິການ Google Play ທີ່ບາງແອັບພລິເຄຊັນຂອງທ່ານຕ້ອງອາໄສນັ້ນ ບໍ່ຖືກຮອງຮັບໃນອຸປະກອນຂອງທ່ານ. ກະລຸນາຕິດຕໍ່ຜູ້ຜະລິດສຳລັບການແນະນຳ." + "ວັນທີຂອງອຸປະກອນບໍ່ຖືກຕ້ອງ. ກະລຸນາກວດສອບວັນທີຂອງອຸປະກອນຂອງທ່ານ." + "ອັບເດດ" + "ເຂົ້າສູ່ລະບົບ" + "ເຂົ້າສູ່ລະບົບດ້ວຍ Google" + + "ແອັບພລິເຄຊັນໄດ້ພະຍາຍາມໃຊ້ Google Play Services ເວີຊັນທີ່ບໍ່ສາມາດໃຊ້ໄດ້." + "ແອັບພລິເຄຊັນຕ້ອງການເປີດນຳໃຊ້ Google Play Services." + "ແອັບພລິເຄຊັນຕ້ອງການໃຫ້ຕິດຕັ້ງ Google Play Services." + "ແອັບພລິເຄຊັນຕ້ອງການອັບເດດ Google Play Services." + "ບໍລິການ Google Play ຜິດພາດ" + "ຮ້ອງຂໍໂດຍ %1$s" + diff --git a/libs/google-play-services_lib/res/values-lt/strings.xml b/libs/google-play-services_lib/res/values-lt/strings.xml new file mode 100644 index 0000000..73de5fa --- /dev/null +++ b/libs/google-play-services_lib/res/values-lt/strings.xml @@ -0,0 +1,31 @@ + + + "Gauti „Google Play“ paslaugų" + "Ši programa neveiks be „Google Play“ paslaugų, kurios neįdiegtos telefone." + "Ši programa neveiks be „Google Play“ paslaugų, kurios neįdiegtos planšetiniame kompiuteryje." + "Gauti „Google Play“ paslaugų" + "Įgalinti „Google Play“ paslaugas" + "Ši programa neveiks, jei neįgalinsite „Google Play“ paslaugų." + "Įgal. „Google Play“ paslaugas" + "Atnaujinti „Google Play“ paslaugas" + "Ši programa neveiks, jei neatnaujinsite „Google Play“ paslaugų." + "Tinklo klaida" + "Norint prisijungti prie „Google Play“ paslaugų reikia duomenų ryšio." + "Netinkama paskyra" + "Nurodytos paskyros šiame įrenginyje nėra. Pasirinkite kitą paskyrą." + "Nežinoma „Google Play“ paslaugų problema." + "„Google Play“ paslaugos" + "Jūsų įrenginys nepalaiko „Google Play“ paslaugų, kuriomis remiasi kai kurios programos. Jei reikia pagalbos, susisiekite su gamintoju." + "Įrenginyje nurodyta data neteisinga. Patikrinkite įrenginyje nurodytą datą." + "Atnaujinti" + "Prisij." + "Prisij. naud. „Google“" + + "Programa bandė naudotis netinkama „Google Play“ paslaugų versija." + "Norint naudoti programą būtina įgalinti „Google Play“ paslaugas." + "Norint naudoti programą būtina įdiegti „Google Play“ paslaugas." + "Norint naudoti programą būtina atnaujinti „Google Play“ paslaugas." + "„Google Play“ paslaugų klaida" + "Užklausą pateikė „%1$s“" + diff --git a/libs/google-play-services_lib/res/values-lv/strings.xml b/libs/google-play-services_lib/res/values-lv/strings.xml new file mode 100644 index 0000000..9e4b6ee --- /dev/null +++ b/libs/google-play-services_lib/res/values-lv/strings.xml @@ -0,0 +1,31 @@ + + + "Google Play pakalpojumu iegūšana" + "Lai šī lietotne darbotos, tālrunī ir jāinstalē Google Play pakalpojumi." + "Lai šī lietotne darbotos, planšetdatorā ir jāinstalē Google Play pakalpojumi." + "Iegūt Google Play pakalpojumus" + "Google Play pakalpojumu iespējošana" + "Lai šī lietotne darbotos, iespējojiet Google Play pakalpojumus." + "Iespējot Google Play pakalpojumus" + "Google Play pakalpojumu atjaunināšana" + "Lai šī lietotne darbotos, atjauniniet Google Play pakalpojumus." + "Tīkla kļūda" + "Lai izveidotu savienojumu ar Google Play pakalpojumiem, ir nepieciešams datu savienojums." + "Nederīgs konts" + "Norādītais konts šajā ierīcē nepastāv. Lūdzu, izvēlieties citu kontu." + "Nezināma problēma ar Google Play pakalpojumiem." + "Google Play pakalpojumi" + "Jūsu ierīce neatbalsta Google Play pakalpojumus, kuri nepieciešami dažu jūsu lietojumprogrammu darbībai. Lūdzu, sazinieties ar ražotāju, lai saņemtu palīdzību." + "Šķiet, ka ierīcē ir iestatīts nepareizs datums. Lūdzu, pārbaudiet ierīces datumu." + "Atjaunināt" + "Pierakst." + "Pierakstīties Google" + + "Lietojumpr. mēģināja izmantot nederīgu Google Play pakalp. versiju." + "Lai lietojumprogramma darbotos, ir jāiespējo Google Play pakalpojumi." + "Lai lietojumprogramma darbotos, ir jāinstalē Google Play pakalpojumi." + "Lai lietojumprogramma darbotos, jāatjaunina Google Play pakalpojumi." + "Google Play pakalpojumu kļūda" + "Pieprasījums no lietotnes %1$s" + diff --git a/libs/google-play-services_lib/res/values-mn-rMN/strings.xml b/libs/google-play-services_lib/res/values-mn-rMN/strings.xml new file mode 100644 index 0000000..1743256 --- /dev/null +++ b/libs/google-play-services_lib/res/values-mn-rMN/strings.xml @@ -0,0 +1,31 @@ + + + "Google Play үйлчилгээ авах" + "Таны утсанд байхгүй байгаа Google Play үйлчилгээг идэвхжүүлж байж энэ апп-г ажиллуулах боломжтой." + "Таны таблетэд байхгүй Google Play үйлчилгээг идэвхжүүлж байж энэ апп-г ажиллуулах боломжтой." + "Google Play үйлчилгээ авах" + "Google Play үйлчилгээг идэвхжүүлэх" + "Та Google Play үйлчилгээг идэвхжүүлж байж энэ апп-г ажиллуулах боломжтой." + "Google Play үйлчилгээг идэвхжүүлэх" + "Google Play үйлчилгээг шинэчлэх" + "Та Google Play үйлчилгээг шинэчлэхгүй бол энэ апп ажиллах боломжгүй." + "Сүлжээний алдаа" + "Google Play үйлчилгээнд холбогдохын тулд дата холболт шаардлагатай." + "Буруу акаунт" + "Заасан акаунт энэ төхөөрөмж дээр байхгүй байна. Өөр акаунт сонгоно уу." + "Google Play үйлчилгээтэй холбоотой тодорхойгүй алдаа." + "Google Play үйлчилгээ" + "Таны зарим аппликешнүүдийн хамаардаг Google Play үйлчилгээ таны төхөөрөмжид дэмжигдэхгүй байна. Тусламж авахын тулд үйлдвэрлэгчтэй холбоо барина уу." + "Төхөөрөмжийн огноо буруу байгаа бололтой. Төхөөрөмжийн огноог шалгана уу." + "Шинэчлэх" + "Нэвтрэх" + "Google-р нэвтрэх:" + + "Аппликешн Google Play Үйлчилгээний муу хувилбарыг ашиглахыг оролдлоо." + "Аппликешн Google Play Үйлчилгээг идэвхжүүлсэн байхыг шаардана." + "Аппликешн Google Play Үйлчилгээг суулгахыг шаардана." + "Аппликешн Google Play Үйлчилгээг шинэчлэхийг шаардана." + "Google Play үйлчилгээний алдаа" + "Хүсэлт гаргасан %1$s" + diff --git a/libs/google-play-services_lib/res/values-ms-rMY/strings.xml b/libs/google-play-services_lib/res/values-ms-rMY/strings.xml new file mode 100644 index 0000000..8e8a4b9 --- /dev/null +++ b/libs/google-play-services_lib/res/values-ms-rMY/strings.xml @@ -0,0 +1,31 @@ + + + "Dapatkan perkhidmatan Google Play" + "Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada telefon anda." + "Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada tablet anda." + "Dapatkan perkhidmatan Google Play" + "Dayakan perkhidmatan Google Play" + "Apl ini tidak akan berfungsi kecuali anda mendayakan perkhidmatan Google Play." + "Dayakan perkhidmatan Google Play" + "Kemas kini perkhidmatan Google Play" + "Apl ini tidak akan berfungsi kecuali anda mengemas kini perkhidmatan Google Play." + "Ralat Rangkaian" + "Sambungan data diperlukan untuk menyambung ke perkhidmatan Google Play." + "Akaun Tidak Sah" + "Akaun yang dinyatakan tidak wujud pada peranti ini. Sila pilih akaun yang lain." + "Isu tidak diketahui dengan perkhidmatan Google Play." + "Perkhidmatan Google Play" + "Peranti anda tidak menyokong perkhidmatan Google Play, sedangkan sesetengah aplikasi anda memerlukannya. Sila hubungi pengilang untuk bantuan." + "Tarikh pada peranti kelihatan tidak betul. Sila semak tarikh pada peranti." + "Kemas kini" + "Log masuk" + "Log masuk dengan Google" + + "Aplikasi cuba menggunakan versi Perkhidmatan Google Play yang rosak." + "Perkhidmatan Google Play perlu didayakan untuk menggunakan aplikasi." + "Perkhidmatan Google Play perlu dipasang untuk mengguankan aplikasi." + "Perkhidmatan Google Play perlu dikemas kini untuk menggunakan aplikasi." + "Ralat perkhidmatan Google Play" + "Diminta oleh %1$s" + diff --git a/libs/google-play-services_lib/res/values-ms/strings.xml b/libs/google-play-services_lib/res/values-ms/strings.xml new file mode 100644 index 0000000..8e8a4b9 --- /dev/null +++ b/libs/google-play-services_lib/res/values-ms/strings.xml @@ -0,0 +1,31 @@ + + + "Dapatkan perkhidmatan Google Play" + "Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada telefon anda." + "Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada tablet anda." + "Dapatkan perkhidmatan Google Play" + "Dayakan perkhidmatan Google Play" + "Apl ini tidak akan berfungsi kecuali anda mendayakan perkhidmatan Google Play." + "Dayakan perkhidmatan Google Play" + "Kemas kini perkhidmatan Google Play" + "Apl ini tidak akan berfungsi kecuali anda mengemas kini perkhidmatan Google Play." + "Ralat Rangkaian" + "Sambungan data diperlukan untuk menyambung ke perkhidmatan Google Play." + "Akaun Tidak Sah" + "Akaun yang dinyatakan tidak wujud pada peranti ini. Sila pilih akaun yang lain." + "Isu tidak diketahui dengan perkhidmatan Google Play." + "Perkhidmatan Google Play" + "Peranti anda tidak menyokong perkhidmatan Google Play, sedangkan sesetengah aplikasi anda memerlukannya. Sila hubungi pengilang untuk bantuan." + "Tarikh pada peranti kelihatan tidak betul. Sila semak tarikh pada peranti." + "Kemas kini" + "Log masuk" + "Log masuk dengan Google" + + "Aplikasi cuba menggunakan versi Perkhidmatan Google Play yang rosak." + "Perkhidmatan Google Play perlu didayakan untuk menggunakan aplikasi." + "Perkhidmatan Google Play perlu dipasang untuk mengguankan aplikasi." + "Perkhidmatan Google Play perlu dikemas kini untuk menggunakan aplikasi." + "Ralat perkhidmatan Google Play" + "Diminta oleh %1$s" + diff --git a/libs/google-play-services_lib/res/values-nb/strings.xml b/libs/google-play-services_lib/res/values-nb/strings.xml new file mode 100644 index 0000000..1e16bbb --- /dev/null +++ b/libs/google-play-services_lib/res/values-nb/strings.xml @@ -0,0 +1,31 @@ + + + "Installer Google Play Tjenester" + "Denne appen kan ikke kjøres uten Google Play Tjenester, som ikke er installert på telefonen din." + "Denne appen kan ikke kjøres uten Google Play Tjenester, som ikke er installert på nettbrettet ditt." + "Installer Google Play Tjenester" + "Aktiver Google Play Tjenester" + "Denne appen fungerer ikke med mindre du aktiverer Google Play Tjenester." + "Aktiver Google Play Tjenester" + "Oppdater Google Play Tjenester" + "Denne appen kan ikke kjøres før du oppdaterer Google Play Tjenester." + "Nettverksfeil" + "Du må ha datatilkobling for å koble deg til Google Play-tjenester." + "Ugyldig konto" + "Den angitte kontoen finnes ikke på enheten. Velg en annen konto." + "Det oppsto et ukjent problem med Google Play Tjenester." + "Google Play-tjenester" + "Google Play Tjenester, som noen av appene er avhengige av, støttes ikke av enheten. Ta kontakt med produsenten for å få hjelp." + "Datoen på enheten ser ut til å være feil. Sjekk datoen på enheten." + "Oppdater" + "Logg på" + "Logg inn med Google" + + "En app prøvde å bruke en skadet versjon av Google Play Tjenester." + "En app krever Google Play Tjenester for å aktiveres." + "En app krever at Google Play Tjenester installeres." + "En app krever at Google Play Tjenester oppdateres." + "Google Play Tjenester-feil" + "Forespurt av %1$s" + diff --git a/libs/google-play-services_lib/res/values-nl/strings.xml b/libs/google-play-services_lib/res/values-nl/strings.xml new file mode 100644 index 0000000..f38db5f --- /dev/null +++ b/libs/google-play-services_lib/res/values-nl/strings.xml @@ -0,0 +1,31 @@ + + + "Google Play-services ophalen" + "Deze app kan niet worden uitgevoerd zonder Google Play-services die ontbreken op uw telefoon." + "Deze app kan niet worden uitgevoerd zonder Google Play-services die ontbreken op uw tablet." + "Google Play-services ophalen" + "Google Play-services inschakelen" + "Deze app werkt niet, tenzij u Google Play-services inschakelt." + "Google Play-services inschak." + "Google Play-services bijwerken" + "Deze app kan niet worden uitgevoerd, tenzij u Google Play-services bijwerkt." + "Netwerkfout" + "Er is een gegevensverbinding nodig om verbinding te kunnen maken met Google Play-services." + "Ongeldig account" + "Het gespecificeerde account bestaat niet op dit apparaat. Kies een ander account." + "Onbekend probleem met Google Play-services." + "Google Play-services" + "Google Play-services, dat vereist is voor een aantal van uw applicaties, wordt niet ondersteund door uw apparaat. Neem contact op met de fabrikant voor ondersteuning." + "De datum op het apparaat lijkt onjuist. Controleer de datum op het apparaat." + "Bijwerken" + "Inloggen" + "Inloggen met Google" + + "Onjuiste versie van Google Play-services wordt gebruikt." + "Google Play-services moet zijn ingeschakeld voor een applicatie." + "Google Play-services moet zijn geïnstalleerd voor een applicatie." + "Google Play-services moet worden geüpdatet voor een applicatie." + "Fout met Google Play-services" + "Aangevraagd door %1$s" + diff --git a/libs/google-play-services_lib/res/values-pl/strings.xml b/libs/google-play-services_lib/res/values-pl/strings.xml new file mode 100644 index 0000000..5eba15f --- /dev/null +++ b/libs/google-play-services_lib/res/values-pl/strings.xml @@ -0,0 +1,31 @@ + + + "Pobierz Usługi Google Play" + "Ta aplikacja nie będzie działać bez Usług Google Play, których nie masz na telefonie." + "Ta aplikacja nie będzie działać bez Usług Google Play, których nie masz na tablecie." + "Pobierz Usługi Google Play" + "Włącz Usługi Google Play" + "Ta aplikacja nie będzie działać, jeśli nie włączysz Usług Google Play." + "Włącz Usługi Google Play" + "Aktualizuj Usługi Google Play" + "Ta aplikacja nie będzie działać, jeśli nie zaktualizujesz Usług Google Play." + "Błąd sieci" + "Korzystanie z usług Google Play wymaga połączenia z internetem." + "Nieprawidłowe konto" + "Podanego konta nie ma na tym urządzeniu. Wybierz inne konto." + "Nieznany problem z Usługami Google Play." + "Usługi Google Play" + "Usługi Google Play, od których zależy działanie niektórych aplikacji, nie są obsługiwane na Twoim urządzeniu. Skontaktuj się z producentem, by uzyskać pomoc." + "Data ustawiona na urządzeniu wydaje się nieprawidłowa. Sprawdź datę ustawioną na urządzeniu." + "Aktualizuj" + "Zaloguj się" + "Zaloguj się przez Google" + + "Aplikacja próbowała skorzystać z nieprawidłowej wersji Usług Google Play." + "Aplikacja wymaga włączenia Usług Google Play." + "Aplikacja wymaga zainstalowania Usług Google Play." + "Aplikacja wymaga aktualizacji Usług Google Play." + "Błąd usług Google Play" + "Żądanie z aplikacji %1$s" + diff --git a/libs/google-play-services_lib/res/values-pt-rBR/strings.xml b/libs/google-play-services_lib/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000..6db462d --- /dev/null +++ b/libs/google-play-services_lib/res/values-pt-rBR/strings.xml @@ -0,0 +1,31 @@ + + + "Instale o Google Play Services" + "Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu telefone." + "Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu tablet." + "Instalar o Google Play Services" + "Ative o Google Play Services" + "Este aplicativo só funciona com o Google Play Services ativado." + "Ativar o Google Play Services" + "Atualize o Google Play Services" + "Este aplicativo só funciona com uma versão atualizada do Google Play Services." + "Erro na rede" + "É necessária uma conexão de dados para conectar ao Google Play Services." + "Conta inválida" + "A conta especificada não existe no dispositivo. Escolha outra conta." + "Problema desconhecido com o Google Play Services." + "Play Services" + "O Google Play Services, necessário para alguns dos aplicativos, não é compatível com seu dispositivo. Entre em contato com o fabricante para obter assistência." + "A data no dispositivo parece incorreta. Verifique a data no dispositivo." + "Atualizar" + "Login" + "Fazer login com o Google" + + "Um aplicativo tentou usar uma versão errada do Google Play Services." + "Um aplicativo requer a ativação do Google Play Services." + "Um aplicativo requer a instalação do Google Play Services." + "Um aplicativo requer a atualização do Google Play Services." + "Ocorreu um erro no Google Play Services" + "Solicitado por %1$s" + diff --git a/libs/google-play-services_lib/res/values-pt-rPT/strings.xml b/libs/google-play-services_lib/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000..0ceafcb --- /dev/null +++ b/libs/google-play-services_lib/res/values-pt-rPT/strings.xml @@ -0,0 +1,31 @@ + + + "Obter serviços do Google Play" + "Esta aplicação não será executada sem os serviços do Google Play, que estão em falta no seu telemóvel." + "Esta aplicação não será executada sem os serviços do Google Play, que estão em falta no seu tablet." + "Obter serviços do Google Play" + "Ativar serviços do Google Play" + "Esta aplicação não funcionará enquanto não ativar os serviços do Google Play." + "Ativar serviços do Google Play" + "Atualizar serviços do Google Play" + "Esta aplicação não será executada enquanto não atualizar os serviços do Google Play." + "Erro de Rede" + "É necessária uma ligação de dados para se ligar aos Serviços do Google Play." + "Conta Inválida" + "A conta especificada não existe neste dispositivo. Escolha uma conta diferente." + "Problema desconhecido nos serviços do Google Play." + "Serviços do Google Play" + "Os serviços do Google Play, dos quais dependem algumas das suas aplicações, não são suportados pelo seu dispositivo. Contacte o fabricante para obter assistência." + "A data no dispositivo parece estar incorreta. Verifique a data no dispositivo." + "Atualizar" + "Inic. ses." + "Inic. sessão com o Google" + + "Aplicação tentou utiliz. versão incorreta dos Serviços do Google Play." + "Uma aplicação necessita da ativação dos Serviços do Google Play." + "Uma aplicação necessita da instalação dos Serviços do Google Play." + "Uma aplicação necessita da atualização dos Serviços do Google Play." + "Erro dos serviços do Google Play" + "Solicitado por %1$s" + diff --git a/libs/google-play-services_lib/res/values-pt/strings.xml b/libs/google-play-services_lib/res/values-pt/strings.xml new file mode 100644 index 0000000..6db462d --- /dev/null +++ b/libs/google-play-services_lib/res/values-pt/strings.xml @@ -0,0 +1,31 @@ + + + "Instale o Google Play Services" + "Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu telefone." + "Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu tablet." + "Instalar o Google Play Services" + "Ative o Google Play Services" + "Este aplicativo só funciona com o Google Play Services ativado." + "Ativar o Google Play Services" + "Atualize o Google Play Services" + "Este aplicativo só funciona com uma versão atualizada do Google Play Services." + "Erro na rede" + "É necessária uma conexão de dados para conectar ao Google Play Services." + "Conta inválida" + "A conta especificada não existe no dispositivo. Escolha outra conta." + "Problema desconhecido com o Google Play Services." + "Play Services" + "O Google Play Services, necessário para alguns dos aplicativos, não é compatível com seu dispositivo. Entre em contato com o fabricante para obter assistência." + "A data no dispositivo parece incorreta. Verifique a data no dispositivo." + "Atualizar" + "Login" + "Fazer login com o Google" + + "Um aplicativo tentou usar uma versão errada do Google Play Services." + "Um aplicativo requer a ativação do Google Play Services." + "Um aplicativo requer a instalação do Google Play Services." + "Um aplicativo requer a atualização do Google Play Services." + "Ocorreu um erro no Google Play Services" + "Solicitado por %1$s" + diff --git a/libs/google-play-services_lib/res/values-ro/strings.xml b/libs/google-play-services_lib/res/values-ro/strings.xml new file mode 100644 index 0000000..eb42896 --- /dev/null +++ b/libs/google-play-services_lib/res/values-ro/strings.xml @@ -0,0 +1,31 @@ + + + "Descărcaţi Servicii Google Play" + "Această aplicaţie nu poate rula fără Servicii Google Play, care lipsesc de pe telefon." + "Această aplicaţie nu poate rula fără Servicii Google Play, care lipsesc de pe tabletă." + "Obţineţi Servicii Google Play" + "Activaţi Servicii Google Play" + "Această aplicaţie nu va funcţiona decât dacă activaţi Servicii Google Play." + "Activaţi Servicii Google Play" + "Actualizaţi Servicii Google Play" + "Această aplicaţie nu poate rula decât dacă actualizaţi Servicii Google Play." + "Eroare de reţea" + "Este necesară o conexiune de date pentru a vă conecta la serviciile Google Play." + "Cont nevalid" + "Contul menționat nu există pe acest dispozitiv. Alegeți alt cont." + "Problemă necunoscută privind Servicii Google Play." + "Servicii Google Play" + "Gadgetul nu acceptă serviciile Google Play, pe care se bazează unele dintre aplicații. Pentru asistență, contactați producătorul gadgetului." + "Data de pe dispozitiv pare să fie incorectă. Verificați data de pe dispozitiv." + "Actualizaţi" + "Conectați" + "Conectați-vă cu Google" + + "Aplicația a încercat să utilizeze o vers. Servicii Google Play greșită" + "O aplicație necesită activarea Serviciilor Google Play." + "O aplicație necesită instalarea Serviciilor Google Play." + "O aplicație necesită o actualizare pentru Servicii Google Play." + "Eroare Servicii Google Play" + "Solicitată de %1$s" + diff --git a/libs/google-play-services_lib/res/values-ru/strings.xml b/libs/google-play-services_lib/res/values-ru/strings.xml new file mode 100644 index 0000000..c784aae --- /dev/null +++ b/libs/google-play-services_lib/res/values-ru/strings.xml @@ -0,0 +1,31 @@ + + + "Установите Сервисы Google Play" + "Для работы этого приложения требуется установить Сервисы Google Play." + "Для работы этого приложения требуется установить Сервисы Google Play." + "Установить" + "Включите Сервисы Google Play" + "Для работы этого приложения требуется включить Сервисы Google Play." + "Включить" + "Обновите Сервисы Google Play" + "Для работы этого приложения требуется обновить Сервисы Google Play." + "Ошибка сети" + "Для работы с Google Play требуется подключение к сети." + "Недействительный аккаунт" + "Этого аккаунта нет на устройстве. Выберите другой." + "Неизвестная ошибка с Сервисами Google Play." + "Сервисы Google Play" + "Сервисы Google Play, необходимые для работы некоторых приложений, не поддерживаются на вашем устройстве. Обратитесь к производителю." + "Проверьте правильность даты, указанной на устройстве." + "Обновить" + "Войти" + "Войти в аккаунт Google" + + "Версия сервисов Google Play неисправна" + "Для работы приложения требуется включить сервисы Google Play" + "Для работы приложения требуется установить сервисы Google Play" + "Для работы приложения требуется обновить сервисы Google Play" + "Ошибка сервисов Google Play" + "Запрос от приложения \"%1$s\"" + diff --git a/libs/google-play-services_lib/res/values-sk/strings.xml b/libs/google-play-services_lib/res/values-sk/strings.xml new file mode 100644 index 0000000..125d87f --- /dev/null +++ b/libs/google-play-services_lib/res/values-sk/strings.xml @@ -0,0 +1,31 @@ + + + "Inštalovať služby Google Play" + "Na spustenie tejto aplikácie sa vyžadujú služby Google Play, ktoré v telefóne nemáte." + "Na spustenie tejto aplikácie sa vyžadujú služby Google Play, ktoré v tablete nemáte." + "Inštalovať služby Google Play" + "Povoliť služby Google Play" + "Táto aplikácia bude fungovať až po povolení služieb Google Play." + "Povoliť služby Google Play" + "Aktualizovať služby Google Play" + "Túto aplikáciu bude možné spustiť až po aktualizácii služieb Google Play." + "Chyba siete" + "Pripojenie k službám Google Play si vyžaduje dátové pripojenie." + "Neplatný účet" + "Zadaný účet v tomto zariadení neexistuje. Vyberte iný účet." + "Neznámy problém so službami Google Play." + "Služby Google Play" + "Niektoré vaše aplikácie vyžadujú služby Google Play, ktoré vo vašom zariadení nie sú podporované. Ak potrebujete pomoc, kontaktujte výrobcu." + "Dátum nastavený v zariadení sa zdá byť nesprávny. Skontrolujte ho." + "Aktualizovať" + "Prihlásiť sa" + "Prihlásiť sa do účtu Google" + + "Aplikácia sa pokúsila použiť nesprávnu verziu služieb Google Play." + "Aplikácia vyžaduje povolenie služieb Google Play." + "Aplikácia vyžaduje inštaláciu služieb Google Play." + "Aplikácia vyžaduje aktualizáciu služieb Google Play." + "Chyba služieb Google Play" + "Vyžiadané aplikáciou %1$s" + diff --git a/libs/google-play-services_lib/res/values-sl/strings.xml b/libs/google-play-services_lib/res/values-sl/strings.xml new file mode 100644 index 0000000..df5821f --- /dev/null +++ b/libs/google-play-services_lib/res/values-sl/strings.xml @@ -0,0 +1,31 @@ + + + "Namestite storitve Google Play" + "Ta aplikacija ne deluje brez storitev Google Play, ki jih ni v telefonu." + "Ta aplikacija ne deluje brez storitev Google Play, ki jih ni v tabličnem računalniku." + "Namestite storitve Google Play" + "Omogočite storitve Google Play" + "Aplikacija ne bo delovala, če ne omogočite storitev Google Play." + "Omogočite storitve Google Play" + "Posodobite storitve Google Play" + "Ta aplikacija ne deluje, če ne posodobite storitev Google Play." + "Omrežna napaka" + "Za povezavo s storitvami Google Play potrebujete internetno povezavo." + "Neveljaven račun" + "V tej napravi ne obstaja navedeni račun. Izberite drugega." + "Neznana težava s storitvami Google Play." + "Storitve Google Play" + "Vaša naprava na podpira storitev Google Play, ki jih potrebujejo nekatere od vaših aplikacij. Za pomoč se obrnite na izdelovalca." + "Videti je, da je datum v napravi napačen. Preverite ga." + "Posodobi" + "Prijava" + "Prijavite se v Google" + + "Aplikacija je poskusila uporabiti napačno različico Storitev Google Play." + "Za delovanje aplikacije morate omogočiti Storitve Google Play." + "Za delovanje aplikacije morate namestiti Storitve Google Play." + "Za delovanje aplikacije morate posodobiti Storitve Google Play." + "Napaka storitev Google Play" + "Zahtevala aplikacija %1$s" + diff --git a/libs/google-play-services_lib/res/values-sr/strings.xml b/libs/google-play-services_lib/res/values-sr/strings.xml new file mode 100644 index 0000000..ad0b549 --- /dev/null +++ b/libs/google-play-services_lib/res/values-sr/strings.xml @@ -0,0 +1,31 @@ + + + "Преузимање Google Play услуга" + "Ова апликација не може да се покрене без Google Play услуга, које недостају на телефону." + "Ова апликација не може да се покрене без Google Play услуга, које недостају на таблету." + "Преузми Google Play услуге" + "Омогућавање Google Play услуга" + "Ова апликација неће функционисати ако не омогућите Google Play услуге." + "Омогући Google Play услуге" + "Ажурирање Google Play услуга" + "Ова апликација не може да се покрене ако не ажурирате Google Play услуге." + "Грешка на мрежи" + "За повезивање са Google Play услугама потребна је веза за пренос података." + "Неважећи налог" + "Наведени налог не постоји на овом уређају. Одаберите други налог." + "Непознат проблем са Google Play услугама." + "Google Play услуге" + "Google Play услуге, које су потребне за функционисање неких од апликација, нису подржане на уређају. Контактирајте произвођача да бисте добили помоћ." + "Изгледа да су подаци на уређају нетачни. Проверите датум на уређају." + "Ажурирај" + "Пријави ме" + "Пријави ме преко Google-а" + + "Апликација је покушала да користи лошу верзију Google Play услуга." + "Апликација захтева да Google Play услуге буду омогућене." + "Апликација захтева инсталирање Google Play услуга." + "Апликација захтева ажурирање Google Play услуга." + "Грешка Google Play услуга" + "Захтева %1$s" + diff --git a/libs/google-play-services_lib/res/values-sv/strings.xml b/libs/google-play-services_lib/res/values-sv/strings.xml new file mode 100644 index 0000000..6a10395 --- /dev/null +++ b/libs/google-play-services_lib/res/values-sv/strings.xml @@ -0,0 +1,31 @@ + + + "Hämta Google Play Tjänster" + "Den här appen kan inte köras utan Google Play Tjänster, som saknas på mobilen." + "Den här appen kan inte köras utan Google Play Tjänster, som saknas på surfplattan." + "Hämta Google Play Tjänster" + "Aktivera Google Play Tjänster" + "Du måste aktivera Google Play Tjänster för att den här appen ska fungera." + "Aktivera Google Play Tjänster" + "Uppdatera Google Play Tjänster" + "Du måste uppdatera Google Play Tjänster innan du kan köra den här appen." + "Nätverksfel" + "En dataanslutning krävs för att ansluta till Google Plays tjänster." + "Ogiltigt konto" + "Det angivna kontot finns inte på den här enheten. Välj ett annat konto." + "Okänt problem med Google Play Tjänster" + "Google Play-tjänster" + "Några av dina appar använder Google Play-tjänster som inte stöds av din enhet. Kontakta tillverkaren om du vill ha hjälp." + "Datumet på enheten verkar inte vara rätt. Kontrollera datumet på enheten." + "Uppdatera" + "Logga in" + "Logga in med Google" + + "En olämplig version av Google Play Tjänster anropades av en app." + "Google Play Tjänster måste aktiveras för en att app ska fungera." + "Google Play Tjänster måste installeras för att en app ska fungera." + "Google Play Tjänster måste uppdateras för en app ska fungera." + "Fel på Google Play Tjänster" + "Begärdes av %1$s" + diff --git a/libs/google-play-services_lib/res/values-sw/strings.xml b/libs/google-play-services_lib/res/values-sw/strings.xml new file mode 100644 index 0000000..37bd92a --- /dev/null +++ b/libs/google-play-services_lib/res/values-sw/strings.xml @@ -0,0 +1,31 @@ + + + "Pata huduma za Google Play" + "Programu hii haiwezi kuendeshwa bila huduma za Google Play, ambazo hazipo kwenye simu yako." + "Programu hii haiwezi kuendeshwa bila huduma za Google Play, ambazo hazipo kwenye kompyuta yako ndogo." + "Pata huduma za Google Play" + "Wezesha huduma za Google Play" + "Programu hii haitafanya kazi mpaka utakapowezesha huduma za Google Play." + "Wezesha huduma za Google Play" + "Sasisha huduma za Google Play" + "Programu hii haiwezi kuendeshwa mpaka utakaposasisha huduma za Google Play." + "Hitilafu ya Mtandao" + "Muunganisho wa data unahitajika ili kuunganisha kwenye huduma za Google Play." + "Akaunti Batili" + "Akaunti iliyobainishwa haipo kwenye kifaa hiki. Tafadhali chagua akaunti tofauti." + "Suala lisilojulikana na huduma za Google Play." + "Huduma za Google Play" + "Huduma za Google Play, ambazo baadhi ya programu zako zinategemea, si linganifu na kifaa chako. Tafadhali wasiliana na mtengenezaji kwa usaidizi." + "Inaeonekana tarehe ya kifaa sio sahihi. Tafadhali angalia tarehe ya kifaa." + "Sasisha" + "Ingia" + "Ingia ukitumia Google" + + "Programu ilijaribu kutumia toleo baya la Huduma za Google Play." + "Programu inahitaji Huduma za Google Play ili kuwashwa." + "Programu inahitaji usakinishaji wa Huduma za Google Play." + "Programu inahitaji sasisho la Huduma za Google Play." + "Hitilafu kwenye Huduma za Google Play" + "Imeombwa na %1$s" + diff --git a/libs/google-play-services_lib/res/values-th/strings.xml b/libs/google-play-services_lib/res/values-th/strings.xml new file mode 100644 index 0000000..6f098fe --- /dev/null +++ b/libs/google-play-services_lib/res/values-th/strings.xml @@ -0,0 +1,31 @@ + + + "รับบริการ Google Play" + "แอปพลิเคชันนี้จะไม่ทำงานหากไม่มีบริการ Google Play ซึ่งไม่มีในโทรศัพท์ของคุณ" + "แอปพลิเคชันนี้จะไม่ทำงานหากไม่มีบริการ Google Play ซึ่งไม่มีในแท็บเล็ตของคุณ" + "รับบริการ Google Play" + "เปิดใช้งานบริการ Google Play" + "แอปพลิเคชันนี้จะไม่ทำงานจนกว่าคุณจะเปิดใช้งานบริการ Google Play" + "เปิดใช้งานบริการ Google Play" + "อัปเดตบริการ Google Play" + "แอปพลิเคชันนี้จะไม่ทำงานจนกว่าคุณจะอัปเดตบริการ Google Play" + "ข้อผิดพลาดของเครือข่าย" + "ต้องมีการเขื่อมต่อข้อมูลเพื่อเชื่อมต่อกับบริการ Google Play" + "บัญชีไม่ถูกต้อง" + "บัญชีที่ระบุไม่มีอยู่บนอุปกรณ์นี้ โปรดเลือกบัญชีอื่น" + "ปัญหาที่ไม่รู้จักของบริการ Google Play" + "บริการ Google Play" + "บริการ Google Play ซึ่งใช้งานในบางแอปพลิเคชัน ไม่ได้รับการสนับสนุนโดยอุปกรณ์ของคุณ โปรดติดต่อผู้ผลิตเพื่อขอรับความช่วยเหลือ" + "วันที่บนอุปกรณ์ไม่ถูกต้อง โปรดตรวจสอบวันที่บนอุปกรณ์" + "อัปเดต" + "ลงชื่อใช้" + "ลงชื่อเข้าใช้ด้วย Google" + + "แอปพลิเคชันหนึ่งพยายามใช้เวอร์ชันที่ไม่เหมาะสมของบริการ Google Play" + "แอปพลิเคชันหนึ่งจำเป็นต้องมีบริการ Google Play เพื่อเปิดใช้งาน" + "แอปพลิเคชันหนึ่งจำเป็นต้องมีการติดตั้งบริการ Google Play" + "แอปพลิเคชันหนึ่งจำเป็นต้องมีการอัปเดตสำหรับบริการ Google Play" + "ข้อผิดพลาดของบริการ Google Play" + "ขอโดย %1$s" + diff --git a/libs/google-play-services_lib/res/values-tl/strings.xml b/libs/google-play-services_lib/res/values-tl/strings.xml new file mode 100644 index 0000000..337f73c --- /dev/null +++ b/libs/google-play-services_lib/res/values-tl/strings.xml @@ -0,0 +1,31 @@ + + + "Kumuha ng mga serbisyo ng Google Play" + "Hindi tatakbo ang app na ito nang wala ang mga serbisyo ng Google Play, na wala sa iyong telepono." + "Hindi gagana ang app na ito nang wala ang mga serbisyo ng Google Play, na wala sa iyong tablet." + "Kumuha ng Google Play services" + "Paganahin ang Google Play services" + "Hindi gagana ang app na ito maliban kung papaganahin mo ang mga serbisyo ng Google Play." + "Enable Google Play services" + "I-update ang mga serbisyo ng Google Play" + "Hindi gagana ang app na ito maliban kung i-a-update mo ang mga serbisyo ng Google Play." + "May Error sa Network" + "Kailangan ng koneksyon ng data upang makakonekta sa mga serbisyo ng Google Play." + "Di-wasto ang Account" + "Hindi umiiral ang tinukoy na account sa device na ito. Mangyaring pumili ng ibang account." + "May hindi alam na isyu sa mga serbisyo ng Google Play." + "Mga serbisyo ng Google Play" + "Ang mga serbisyo ng Google Play, kung saan nakadepende ang ilan sa iyong mga application, ay hindi sinusuportahan ng iyong device. Mangyaring makipag-ugnay sa manufacturer para sa tulong." + "Mukhang hindi tama ang petsa sa device. Pakisuri ang petsa sa device." + "I-update" + "Sign in" + "Mag-sign in sa Google" + + "May app na sumubok ng maling bersyon ng Mga Serbisyo ng Google Play." + "Kailangan ng application na na-enable ang Mga Serbisyo ng Google Play." + "Kailangan ng application na ma-install ang Serbisyo ng Google Play." + "Kailangan ng application na i-update ang Mga Serbisyo ng Google Play." + "Error sa mga serbisyo ng Google Play" + "Hiniling ng %1$s" + diff --git a/libs/google-play-services_lib/res/values-tr/strings.xml b/libs/google-play-services_lib/res/values-tr/strings.xml new file mode 100644 index 0000000..17e61e5 --- /dev/null +++ b/libs/google-play-services_lib/res/values-tr/strings.xml @@ -0,0 +1,31 @@ + + + "Google Play hizmetlerini edinin" + "Google Play Hizmetleri telefonunuzda yok ve bu uygulama Google Play Hizmetleri olmadan çalışmaz." + "Google Play Hizmetleri tabletinizde yok ve bu uygulama Google Play Hizmetleri olmadan çalışmaz." + "Google Play hizmetlerini edin" + "Google Play hizmetlerini etkinleştir" + "Bu uygulama, Google Play Hizmetleri etkinleştirilmeden çalışmaz" + "Google Play hizmetlerini etkinleştir" + "Google Play hizmetlerini güncelle" + "Bu uygulama Google Play Hizmetleri güncellenmeden çalışmaz." + "Ağ Hatası" + "Google Play hizmetlerine bağlanmak için bir veri bağlantısı gerekiyor." + "Geçersiz Hesap" + "Belirtilen hesap bu cihazda mevcut değil. Lütfen farklı bir hesap seçin." + "Google Play hizmetleriyle ilgili bilinmeyen sorun." + "Google Play hizmetleri" + "Cihazınız, uygulamalarınızdan bazıları için gerekli olan Google Play hizmetlerini desteklemiyor. Lütfen yardım için üreticiyle iletişim kurun." + "Cihazdaki tarih doğru görünmüyor. Lütfen cihazda ayarlı tarihi kontrol edin." + "Güncelle" + "Oturum aç" + "Google\'da oturum aç" + + "Bir uygulama, Google Play Hizmetleri\'nin bozuk bir sürümünü kullanmayı denedi." + "Bir uygulama, Google Play Hizmetleri\'nin etkin olmasını gerektiriyor." + "Bir uygulama, Google Play Hizmetleri\'nin yüklenmesini gerektiriyor." + "Bir uygulama, Google Play Hizmetleri için bir güncelleme gerektiriyor." + "Google Play hizmetleri hatası" + "İstekte bulunan: %1$s" + diff --git a/libs/google-play-services_lib/res/values-uk/strings.xml b/libs/google-play-services_lib/res/values-uk/strings.xml new file mode 100644 index 0000000..d657aea --- /dev/null +++ b/libs/google-play-services_lib/res/values-uk/strings.xml @@ -0,0 +1,31 @@ + + + "Установити Google Play Послуги" + "Ця програма не запуститься без Google Play Послуг, яких немає у вашому телефоні." + "Ця програма не запуститься без Google Play Послуг, яких немає на вашому планшетному ПК." + "Установити Google Play Послуги" + "Увімкнути Google Play Послуги" + "Ця програма не працюватиме, поки ви не ввімкнете Google Play Послуги." + "Увімкнути Google Play Послуги" + "Оновити Google Play Послуги" + "Ця програма не запуститься, поки ви не оновите Google Play Послуги." + "Помилка мережі" + "Для під’єднання до сервісів Google Play потрібне з’єднання з мережею." + "Недійсний обліковий запис" + "Указаний обліковий запис не існує на цьому пристрої. Виберіть інший обліковий запис." + "Google Play Послуги – невідома проблема." + "Сервіси Google Play" + "Ваш пристрій не підтримує Сервіси Google Play, від яких залежить робота деяких програм. Зверніться по допомогу до виробника." + "Схоже, на пристрої вказано неправильну дату. Перевірте її." + "Оновити" + "Увійти" + "Увійти в обл.запис Google" + + "Програма спробувала застосувати хибну версію Сервісів Google Play." + "Щоб програма працювала, потрібно ввімкнути Сервіси Google Play." + "Щоб програма працювала, потрібно встановити Сервіси Google Play." + "Щоб програма працювала, потрібно оновити Сервіси Google Play." + "Помилка Сервісів Google Play" + "Запит від програми %1$s" + diff --git a/libs/google-play-services_lib/res/values-vi/strings.xml b/libs/google-play-services_lib/res/values-vi/strings.xml new file mode 100644 index 0000000..a0434a0 --- /dev/null +++ b/libs/google-play-services_lib/res/values-vi/strings.xml @@ -0,0 +1,31 @@ + + + "Cài đặt dịch vụ của Google Play" + "Ứng dụng này sẽ không chạy nếu không có dịch vụ của Google Play. Điện thoại của bạn bị thiếu dịch vụ này." + "Ứng dụng này sẽ không chạy nếu không có dịch vụ của Google Play. Máy tính bảng của bạn bị thiếu dịch vụ này." + "Cài đặt dịch vụ của Google Play" + "Bật dịch vụ của Google Play" + "Ứng dụng này sẽ không hoạt động trừ khi bạn bật dịch vụ của Google Play." + "Bật dịch vụ của Google Play" + "Cập nhật dịch vụ của Google Play" + "Ứng dụng này sẽ không chạy trừ khi bạn cập nhật dịch vụ của Google Play." + "Lỗi mạng" + "Cần có kết nối dữ liệu để kết nối với các dịch vụ của Google Play." + "Tài khoản không hợp lệ" + "Tài khoản đã chỉ định không tồn tại trên thiết bị này. Vui lòng chọn một tài khoản khác." + "Sự cố không xác định với dịch vụ của Google Play." + "Dịch vụ của Google Play" + "Các dịch vụ của Google Play mà một số ứng dụng của bạn dựa vào không được thiết bị của bạn hỗ trợ. Vui lòng liên hệ với nhà sản xuất để được hỗ trợ." + "Ngày trên thiết bị có vẻ không chính xác. Vui lòng kiểm tra ngày trên thiết bị." + "Cập nhật" + "Đăng nhập" + "Đăng nhập bằng Google" + + "Ứng dụng đã cố sử dụng phiên bản không đúng của Dịch vụ của Google Play." + "Ứng dụng yêu cầu Dịch vụ của Google Play phải được bật." + "Ứng dụng yêu cầu cài đặt Dịch vụ của Google Play." + "Ứng dụng yêu cầu cập nhật dành cho Dịch vụ Google Play." + "Lỗi dịch vụ của Google Play" + "Được yêu cầu bởi %1$s" + diff --git a/libs/google-play-services_lib/res/values-zh-rCN/strings.xml b/libs/google-play-services_lib/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000..4339e3e --- /dev/null +++ b/libs/google-play-services_lib/res/values-zh-rCN/strings.xml @@ -0,0 +1,31 @@ + + + "获取 Google Play 服务" + "您的手机中没有 Google Play 服务,您必须先安装该服务才能运行此应用。" + "您的平板电脑中没有 Google Play 服务,您必须先安装该服务才能运行此应用。" + "获取 Google Play 服务" + "启用 Google Play 服务" + "您必须先启用 Google Play 服务才能运行此应用。" + "启用 Google Play 服务" + "更新 Google Play 服务" + "您必须先更新 Google Play 服务才能运行此应用。" + "网络错误" + "您必须有数据网络连接才能接入 Google Play 服务。" + "无效帐户" + "此设备上不存在指定的帐户,请选择其他帐户。" + "Google Play 服务出现未知问题。" + "Google Play 服务" + "您的设备不支持部分应用所依赖的 Google Play 服务。请与设备制造商联系,以寻求帮助。" + "设备上的日期似乎不正确,请在设备上检查日期。" + "更新" + "登录" + "使用 Google 帐户登录" + + "某个应用尝试使用的 Google Play 服务版本有误。" + "某个应用要求启用 Google Play 服务。" + "某个应用要求安装 Google Play 服务。" + "某个应用要求更新 Google Play 服务。" + "Google Play 服务出错" + "由“%1$s”发出" + diff --git a/libs/google-play-services_lib/res/values-zh-rHK/strings.xml b/libs/google-play-services_lib/res/values-zh-rHK/strings.xml new file mode 100644 index 0000000..abe6cf1 --- /dev/null +++ b/libs/google-play-services_lib/res/values-zh-rHK/strings.xml @@ -0,0 +1,31 @@ + + + "取得 Google Play 服務" + "您的手機未安裝 Google Play 服務,安裝後才能執行這個應用程式。" + "您的平板電腦未安裝 Google Play 服務,安裝後才能執行這個應用程式。" + "取得 Google Play 服務" + "啟用 Google Play 服務" + "您必須啟用 Google Play 服務,才能執行這個應用程式。" + "啟用 Google Play 服務" + "更新 Google Play 服務" + "您必須更新 Google Play 服務,才能執行這個應用程式。" + "網絡錯誤" + "要連接 Google Play 服務,必需數據連線。" + "無效的帳戶" + "這個裝置上沒有您指定的帳戶,請選擇其他帳戶。" + "Google Play 服務出現不明問題。" + "Google Play 服務" + "您的裝置不支援部分應用程式所需的 Google Play 服務。如需協助,請與您的裝置製造商聯絡。" + "裝置上的日期看來不正確,請檢查裝置上的日期。" + "更新" + "登入" + "登入 Google" + + "應用程式嘗試使用錯誤版本的「Google Play 服務」。" + "必須啟用「Google Play 服務」,才能使用應用程式。" + "必須安裝「Google Play 服務」,才能使用應用程式。" + "必須更新「Google Play 服務」,才能使用應用程式。" + "Google Play 服務錯誤" + "「%1$s」提出要求" + diff --git a/libs/google-play-services_lib/res/values-zh-rTW/strings.xml b/libs/google-play-services_lib/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000..a66018a --- /dev/null +++ b/libs/google-play-services_lib/res/values-zh-rTW/strings.xml @@ -0,0 +1,31 @@ + + + "取得 Google Play 服務" + "您的手機並未安裝 Google Play 服務,所以無法執行這個應用程式。" + "您的平板電腦並未安裝 Google Play 服務,所以無法執行這個應用程式。" + "取得 Google Play 服務" + "啟用 Google Play 服務" + "您必須啟用 Google Play 服務,這個應用程式才能運作。" + "啟用 Google Play 服務" + "更新 Google Play 服務" + "您必須更新 Google Play 服務,才能執行這個應用程式。" + "網路錯誤" + "需要數據連線才能連上 Google Play 服務。" + "無效的帳戶" + "這個裝置上沒有您所指定的帳戶,請選擇其他帳戶。" + "Google Play 服務發生不明問題。" + "Google Play 服務" + "您的裝置不支援部分應用程式所需的 Google Play 服務。如需協助,請與您的裝置製造商聯絡。" + "裝置上的日期似乎不正確,請檢查裝置上的日期。" + "更新" + "登入" + "使用 Google 帳戶登入" + + "應用程式嘗試使用的 Google Play 服務版本有誤。" + "應用程式需要啟用 Google Play 服務。" + "應用程式需要安裝 Google Play 服務。" + "應用程式需要更新 Google Play 服務。" + "Google Play 服務錯誤" + "提出要求的應用程式:%1$s" + diff --git a/libs/google-play-services_lib/res/values-zu/strings.xml b/libs/google-play-services_lib/res/values-zu/strings.xml new file mode 100644 index 0000000..572d9a5 --- /dev/null +++ b/libs/google-play-services_lib/res/values-zu/strings.xml @@ -0,0 +1,31 @@ + + + "Thola amasevisi e-Google Play" + "Lolu hlelo lokusebenza ngeke lusebenze ngaphandle kwamasevisi e-Google Play, angekho efonini yakho." + "Lolu hlelo lokusebenza ngeke lusebenze ngaphandle kwamasevisi e-Google Play, angekho kuthebulethi yakho." + "Thola amasevisi e-Google Play" + "Nika amandla amasevisi e-Google Play" + "Lolu hlelo lokusebenza ngeke lusebenze ngaphandle nje kokuthi unike amandla amasevisi e-Google Play." + "Nika amandla amasevisi e-Google Play" + "Buyekeza amasevisi e-Google Play" + "Lolu hlelo lokusebenza ngeke lusebenze ngaphandle nje kokuthi ubuyekeze amasevisi e-Google Play." + "Iphutha lenethiwekhi" + "Kudingeka ukuxhumeka kwedatha ukuze kuxhunyekwe kumasevisi we-Google Play." + "I-Akhawunti engavumelekile" + "I-Akhawunti ecacisiwe ayikho kule divayisi. Sicela ukhethe i-akhawunti ehlukile." + "Indaba engaziwa yamasevisi we-Google Play" + "Amasevisi we-Google Play" + "Amasevisi we-Google Play, okungukuthi ezinye izinhlelo zakho zithembele kuwo, awasekelwe yidivayisi yakho. Sicela uxhumane nomkhiqizi ukuze uthole usizo." + "Idethi kudivayisi ibonakala ingalungile. Sicela uhlole idethi kudivayisi." + "Isibuyekezo" + "Ngena ngemvume" + "Ngena ngemvume nge-Google" + + "Uhlelo lokusebenza luzame ukusebenzisa inguqulo embi yamasevisi we-Google Play." + "Uhlelo lokusebenza ludinga amasevisi we-Google Play ukuze anikwe amandla." + "Uhlelo lokusebenza ludinga ukufakwa kwamasevisi we-Google Play." + "Uhlelo lokusebenza ludinga isibuyekezo samasevisi we-Google Play." + "Iphutha lamasevisi we-Google Play" + "Kucelwe yi-%1$s" + diff --git a/libs/google-play-services_lib/res/values/ads_attrs.xml b/libs/google-play-services_lib/res/values/ads_attrs.xml new file mode 100644 index 0000000..519a842 --- /dev/null +++ b/libs/google-play-services_lib/res/values/ads_attrs.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/libs/google-play-services_lib/res/values/colors.xml b/libs/google-play-services_lib/res/values/colors.xml new file mode 100644 index 0000000..6b2740a --- /dev/null +++ b/libs/google-play-services_lib/res/values/colors.xml @@ -0,0 +1,14 @@ + + + + @android:color/white + @android:color/white + #FFAAAAAA + @android:color/white + #FF737373 + @android:color/white + #FFAAAAAA + #FF737373 + #FFDD4B39 + #d2d2d2 + \ No newline at end of file diff --git a/libs/google-play-services_lib/res/values/maps_attrs.xml b/libs/google-play-services_lib/res/values/maps_attrs.xml new file mode 100644 index 0000000..aaf65c5 --- /dev/null +++ b/libs/google-play-services_lib/res/values/maps_attrs.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/google-play-services_lib/res/values/strings.xml b/libs/google-play-services_lib/res/values/strings.xml new file mode 100644 index 0000000..24bd58b --- /dev/null +++ b/libs/google-play-services_lib/res/values/strings.xml @@ -0,0 +1,111 @@ + + + + + Get Google Play services + + + This app won\'t run without Google Play services, which are missing from your phone. + + + This app won\'t run without Google Play services, which are missing from your tablet. + + + Get Google Play services + + + Enable Google Play services + + + This app won\'t work unless you enable Google Play services. + + + Enable Google Play services + + + Update Google Play services + + + This app won\'t run unless you update Google Play services. + + + Network Error + + + A data connection is required to connect to Google Play services. + + + Invalid Account + + + The specified account does not exist on this device. Please choose a different account. + + + Unknown issue with Google Play services. + + + Google Play services + + + Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance. + + + The date on the device appears to be incorrect. Please check the date on the device. + + + Update + + + Sign in + + + Sign in with Google + + + + + + An application attempted to use a bad version of Google Play Services. + + + + An application requires Google Play Services to be enabled. + + + + An application requires installation of Google Play Services. + + + + An application requires an update for Google Play Services. + + + + Google Play services error + + + Requested by %1$s + + + + + + + + diff --git a/libs/google-play-services_lib/res/values/version.xml b/libs/google-play-services_lib/res/values/version.xml new file mode 100644 index 0000000..890d911 --- /dev/null +++ b/libs/google-play-services_lib/res/values/version.xml @@ -0,0 +1,4 @@ + + + 4030500 + diff --git a/libs/google-play-services_lib/src/android/UnusedStub.java b/libs/google-play-services_lib/src/android/UnusedStub.java new file mode 100644 index 0000000..d546b0b --- /dev/null +++ b/libs/google-play-services_lib/src/android/UnusedStub.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2013 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. + */ +package android; + +// Stub java file to make inclusion into some IDE's work. +public final class UnusedStub { + private UnusedStub() { } +} diff --git a/lint.xml b/lint.xml new file mode 100644 index 0000000..ee0eead --- /dev/null +++ b/lint.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/project.properties b/project.properties new file mode 100644 index 0000000..12a90b6 --- /dev/null +++ b/project.properties @@ -0,0 +1,16 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-13 +android.library=false +android.library.reference.1=../../git/MobSens/Libraries/google-play-services_lib diff --git a/res/drawable/.DS_Store b/res/drawable/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/res/drawable/.DS_Store differ diff --git a/res/drawable/background.png b/res/drawable/background.png index 3ce01a1..dd3ff24 100644 Binary files a/res/drawable/background.png and b/res/drawable/background.png differ diff --git a/res/drawable/background2.png b/res/drawable/background2.png new file mode 100644 index 0000000..3ce01a1 Binary files /dev/null and b/res/drawable/background2.png differ diff --git a/res/drawable/icon.png b/res/drawable/icon.png index 51ba794..7572bae 100644 Binary files a/res/drawable/icon.png and b/res/drawable/icon.png differ diff --git a/res/layout/help.xml b/res/layout/help.xml index 5746d8f..f5a21f5 100644 --- a/res/layout/help.xml +++ b/res/layout/help.xml @@ -48,21 +48,21 @@ android:layout_marginLeft = "5px" android:layout_marginRight = "5px" /> - - diff --git a/res/layout/main.xml b/res/layout/main.xml index 70dceae..852b744 100644 --- a/res/layout/main.xml +++ b/res/layout/main.xml @@ -8,7 +8,7 @@ - PowerTutor + + PowerTutor2 The Power Profiler will now run after your phone starts up. The Power Profiler will no longer run on when your phone starts up. - This application sends data on power utilization and running applications to the PowerTutor team. We gather nothing allowing us to associate the data with you or your phone; a cryptographically secure hash function is used to protect your identity. Pressing \'Stop\' will prevent these data from being sent. - This application sends data on power utilization and running applications to the PowerTutor team. We gather nothing allowing us to associate the data with you or your phone; a cryptographically secure hash function is used to protect your identity. Pressing \'Start\' will start sending the data from now on. - Your phone type is not recognized by PowerTutor. You may continue to use PowerTutor however we may not be able to get all of the data for your phone and the power calculations may not be accurate. - -

In this version of PowerTutor the Power Profiler service is run on -startup and power consumption traces are sent back to the PowerTutor team. This -helps us identify common power consumption problems for real applications. The -information will be used to improve PowerTutor and recommend power efficiency -improvements to other software, with the end goal of increasing your phone\'s -battery life.\n

\n -

We gather\n - - CPU use\n - - Amount of WiFi/3G traffic (not its content)\n - - Screen brightness\n - - GPS activity (but not location)\n - - Audio use (on/off, volume)\n - - Total power consumption\n - - Application resource utilization\n - - Phone mode, e.g., airplane mode or call status\n -

-

\nWe do NOT gather any of your personal data used in applications -or phone call logs. None of these data will be associate with you or your phone. -We use a cryptographically secure hash function to protect your identity.\n -

\n -

PowerTutor will send back traces only when the phone is plugged in and -will prefer to use Wifi to send back the traces, although your carrier\'s data -service will be used if Wifi is rarely available. If you would like to disable -sending traces you can do so in the menu or by turning off background data in -the android options. -

- PowerTutor - A real-time system and application power monitor. - \n -
    -
  • Main control panel\n + + + Your phone type is not recognized by PowerTutor2. You may continue to use PowerTutor2 however we may not be able to get all of the data for your phone and the power calculations may not be accurate. + + PowerTutor2 - A real-time system and application power monitor. + \n
    • Main control panel\n - Start/stop profiling services. \n - Select Application or System mode to check out power consumption statistics.\n - Menu features:\n - \t* Start/stop sending power traces to the PowerTutor team.\n \t* Enable/Disable the profiling service to run on startup.\n - \t* Save the current power trace to the sdcard.\n -
    • \n -
    • App View\n + \t* Save the current power trace to the sdcard.\n
    • \n
    • App View\n - Displays power usage information for all of the apps running on the phone.\n - Press an app row to go to the Graph View for that app\'s power @@ -54,17 +24,13 @@ the android options. - Data interpretation:\n \t* Percentage value: The percentage of energy/average power consumed by the app in system.\n - \t* Time value: Time that the app has been actively monitored by PowerTutor.\n + \t* Time value: Time that the app has been actively monitored by PowerTutor2.\n - Menu features:\n \t* Change the sort key to one of current power, average power, or total energy usage.\n - \t* Change the time span to include the last minute, hour, day, or all time.\n -
    • \n -
    • Graph View\n + \t* Change the time span to include the last minute, hour, day, or all time.\n
    • \n
    • Graph View\n - Displays app/system power consumption decomposed by hardware component.\n - Use the tabs at the top to move between Chart View and Pie - View.\n -
    • \n -
    • Chart View\n + View.\n
    • \n
    • Chart View\n - Displays the power usage of different components on the phone in recent history.\n - Scroll to view different component power graphs.\n @@ -74,17 +40,11 @@ the android options. \t* Select \"Magnify Recent Data\" to show more recent data points more spread out.\n \t* Select \"Pause\" to freeze the display as is, select resume to - continue.\n -
    • \n -
    • Pie View\n + continue.\n
    • \n
    • Pie View\n - Displays the power usage percentages of the different components.\n - Menu features:\n - \t* Change the time span to include the last minute, hour, day, or all time.\n -
    • \n -
    -
    - + \t* Change the time span to include the last minute, hour, day, or all time.\n
  • \n
+ + -For detailed information, please go to: -http://powertutor.org.\n -
+ \ No newline at end of file diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index a4bb226..23beb2e 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -5,8 +5,4 @@ android:key="runOnStartup" android:title="Run on startup" android:summary="Have the profiling service start when your phone starts" /> - diff --git a/src/edu/umich/PowerTutor/PowerNotifications.aidl b/src/com/henny/PowerTutor2/PowerNotifications.aidl similarity index 98% rename from src/edu/umich/PowerTutor/PowerNotifications.aidl rename to src/com/henny/PowerTutor2/PowerNotifications.aidl index a94d83a..50674a8 100644 --- a/src/edu/umich/PowerTutor/PowerNotifications.aidl +++ b/src/com/henny/PowerTutor2/PowerNotifications.aidl @@ -17,7 +17,7 @@ along with this program. If not, see . Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor; +package com.henny.PowerTutor2; interface PowerNotifications { // These are the notifications that are actually supported. The rest have diff --git a/src/edu/umich/PowerTutor/components/Audio.java b/src/com/henny/PowerTutor2/components/Audio.java similarity index 90% rename from src/edu/umich/PowerTutor/components/Audio.java rename to src/com/henny/PowerTutor2/components/Audio.java index b370b83..9e940a2 100644 --- a/src/edu/umich/PowerTutor/components/Audio.java +++ b/src/com/henny/PowerTutor2/components/Audio.java @@ -14,17 +14,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.components; - -import edu.umich.PowerTutor.PowerNotifications; -import edu.umich.PowerTutor.service.IterationData; -import edu.umich.PowerTutor.service.PowerData; -import edu.umich.PowerTutor.util.NotificationService; -import edu.umich.PowerTutor.util.Recycler; +package com.henny.PowerTutor2.components; +import com.henny.PowerTutor2.PowerNotifications; import android.content.Context; import android.media.AudioManager; @@ -32,6 +26,11 @@ import java.io.OutputStreamWriter; import java.util.TreeSet; +import com.henny.PowerTutor2.service.IterationData; +import com.henny.PowerTutor2.service.PowerData; +import com.henny.PowerTutor2.util.NotificationService; +import com.henny.PowerTutor2.util.Recycler; + /**This class aims to log the audio device status once per log interval*/ public class Audio extends PowerComponent { /**This class is the logger data file corresponding to Audio*/ diff --git a/src/com/henny/PowerTutor2/components/CPU.java b/src/com/henny/PowerTutor2/components/CPU.java new file mode 100644 index 0000000..a6ce861 --- /dev/null +++ b/src/com/henny/PowerTutor2/components/CPU.java @@ -0,0 +1,371 @@ +/* +Copyright (C) 2011 The University of Michigan + +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 . + + */ + +package com.henny.PowerTutor2.components; + +import android.util.Log; +import android.os.Process; +import android.os.SystemClock; +import android.util.SparseArray; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +import com.henny.PowerTutor2.phone.PhoneConstants; +import com.henny.PowerTutor2.service.IterationData; +import com.henny.PowerTutor2.service.PowerData; +import com.henny.PowerTutor2.util.Recycler; +import com.henny.PowerTutor2.util.SystemInfo; + +public class CPU extends PowerComponent { + public static class CpuData extends PowerData { + private static Recycler recycler = new Recycler(); + + public static CpuData obtain() { + CpuData result = recycler.obtain(); + if (result != null) + return result; + return new CpuData(); + } + + @Override + public void recycle() { + recycler.recycle(this); + } + + public double sysPerc; + public double usrPerc; + public double freq; + + private CpuData() { + } + + public void init(double sysPerc, double usrPerc, double freq) { + this.sysPerc = sysPerc; + this.usrPerc = usrPerc; + this.freq = freq; + } + + public void writeLogDataInfo(OutputStreamWriter out) throws IOException { + + StringBuilder res = new StringBuilder(); + res.append("CPU-sys ").append((long) Math.round(sysPerc)) + .append("\nCPU-usr ").append((long) Math.round(usrPerc)) + .append("\nCPU-freq ").append(freq).append("\n"); + out.write(res.toString()); + } + } + + private static final String TAG = "CPU"; + private static final String CPU_FREQ_FILE = "/proc/cpuinfo"; + private static final String STAT_FILE = "/proc/stat"; + + private CpuStateKeeper cpuState; + private SparseArray pidStates; + private SparseArray uidLinks; + + private int[] pids; + private long[] statsBuf; + + private PhoneConstants constants; + + public CPU(PhoneConstants constants) { + this.constants = constants; + cpuState = new CpuStateKeeper(SystemInfo.AID_ALL); + pidStates = new SparseArray(); + uidLinks = new SparseArray(); + statsBuf = new long[7]; + } + + @Override + public IterationData calculateIteration(long iteration) { + IterationData result = IterationData.obtain(); + + SystemInfo sysInfo = SystemInfo.getInstance(); + double freq = readCpuFreq(sysInfo); + if (freq < 0) { + Log.w(TAG, "Failed to read cpu frequency"); + return result; + } + + if (!sysInfo.getUsrSysTotalTime(statsBuf)) { + Log.w(TAG, "Failed to read cpu times"); + return result; + } + + long usrTime = statsBuf[SystemInfo.INDEX_USER_TIME]; + long sysTime = statsBuf[SystemInfo.INDEX_SYS_TIME]; + long totalTime = statsBuf[SystemInfo.INDEX_TOTAL_TIME]; + + boolean init = cpuState.isInitialized(); + cpuState.updateState(usrTime, sysTime, totalTime, iteration); + + if (init) { + CpuData data = CpuData.obtain(); + data.init(cpuState.getUsrPerc(), cpuState.getSysPerc(), freq); + result.setPowerData(data); + } + + uidLinks.clear(); + pids = sysInfo.getPids(pids); + int pidInd = 0; + if (pids != null) + for (int pid : pids) { + if (pid < 0) { + break; + } + + CpuStateKeeper pidState; + if (pidInd < pidStates.size() && pidStates.keyAt(pidInd) == pid) { + pidState = pidStates.valueAt(pidInd); + } else { + int uid = sysInfo.getUidForPid(pid); + if (uid >= 0) { + pidState = new CpuStateKeeper(uid); + pidStates.put(pid, pidState); + } else { + /* Assume that this process no longer exists. */ + continue; + } + } + pidInd++; + + if (!pidState.isStale(iteration)) { + /* + * Nothing much is going on with this pid recently. We'll + * just assume that it's not using any of the cpu for this + * iteration. + */ + pidState.updateIteration(iteration, totalTime); + } else if (sysInfo.getPidUsrSysTime(pid, statsBuf)) { + usrTime = statsBuf[SystemInfo.INDEX_USER_TIME]; + sysTime = statsBuf[SystemInfo.INDEX_SYS_TIME]; + + init = pidState.isInitialized(); + pidState.updateState(usrTime, sysTime, totalTime, iteration); + + if (!init) { + continue; + } + } + + CpuStateKeeper linkState = uidLinks.get(pidState.getUid()); + if (linkState == null) { + uidLinks.put(pidState.getUid(), pidState); + } else { + linkState.absorb(pidState); + } + } + + /* Remove processes that are no longer active. */ + for (int i = 0; i < pidStates.size(); i++) { + if (!pidStates.valueAt(i).isAlive(iteration)) { + pidStates.remove(pidStates.keyAt(i--)); + } + } + + /* Collect the summed uid information. */ + for (int i = 0; i < uidLinks.size(); i++) { + int uid = uidLinks.keyAt(i); + CpuStateKeeper linkState = uidLinks.valueAt(i); + + CpuData uidData = CpuData.obtain(); + predictAppUidState(uidData, linkState.getUsrPerc(), + linkState.getSysPerc(), freq); + result.addUidPowerData(uid, uidData); + } + + return result; + } + + /* + * This is the function that is responsible for predicting the cpu frequency + * state of the individual uid as though it were the only thing running. It + * simply is finding the lowest frequency that keeps the cpu usage under 70% + * assuming there is a linear relationship to the cpu utilization at + * different frequencies. + */ + private void predictAppUidState(CpuData uidData, double usrPerc, + double sysPerc, double freq) { + double[] freqs = constants.cpuFreqs(); + if (usrPerc + sysPerc < 1e-6) { + /* + * Don't waste time with the binary search if there is no + * utilization which will be the case a lot. + */ + uidData.init(sysPerc, usrPerc, freqs[0]); + return; + } + int lo = 0; + int hi = freqs.length - 1; + double perc = sysPerc + usrPerc; + while (lo < hi) { + int mid = (lo + hi) / 2; + double nperc = perc * freq / freqs[mid]; + if (nperc < 70) { + hi = mid; + } else { + lo = mid + 1; + } + } + uidData.init(sysPerc * freq / freqs[lo], usrPerc * freq / freqs[lo], + freqs[lo]); + } + + private static class CpuStateKeeper { + private int uid; + private long iteration; + private long lastUpdateIteration; + private long inactiveIterations; + + private long lastUsr; + private long lastSys; + private long lastTotal; + + private long sumUsr; + private long sumSys; + private long deltaTotal; + + private CpuStateKeeper(int uid) { + this.uid = uid; + lastUsr = lastSys = -1; + lastUpdateIteration = iteration = -1; + inactiveIterations = 0; + } + + public boolean isInitialized() { + return lastUsr != -1; + } + + public void updateIteration(long iteration, long totalTime) { + /* + * Process is still running but actually reading the cpu utilization + * has been skipped this iteration to avoid wasting cpu cycles as + * this process has not been very active recently. + */ + sumUsr = 0; + sumSys = 0; + deltaTotal = totalTime - lastTotal; + if (deltaTotal < 1) + deltaTotal = 1; + lastTotal = totalTime; + this.iteration = iteration; + } + + public void updateState(long usrTime, long sysTime, long totalTime, + long iteration) { + sumUsr = usrTime - lastUsr; + sumSys = sysTime - lastSys; + deltaTotal = totalTime - lastTotal; + if (deltaTotal < 1) + deltaTotal = 1; + lastUsr = usrTime; + lastSys = sysTime; + lastTotal = totalTime; + lastUpdateIteration = this.iteration = iteration; + + if (getUsrPerc() + getSysPerc() < 0.1) { + inactiveIterations++; + } else { + inactiveIterations = 0; + } + } + + public int getUid() { + return uid; + } + + public void absorb(CpuStateKeeper s) { + sumUsr += s.sumUsr; + sumSys += s.sumSys; + } + + public double getUsrPerc() { + return 100.0 * sumUsr / Math.max(sumUsr + sumSys, deltaTotal); + } + + public double getSysPerc() { + return 100.0 * sumSys / Math.max(sumUsr + sumSys, deltaTotal); + } + + public boolean isAlive(long iteration) { + return this.iteration == iteration; + } + + public boolean isStale(long iteration) { + return 1L << (iteration - lastUpdateIteration) > inactiveIterations + * inactiveIterations; + } + } + + @Override + public boolean hasUidInformation() { + return true; + } + + @Override + public String getComponentName() { + return "CPU"; + } + + /* + * Returns the frequency of the processor in Mhz. If the frequency cannot be + * determined returns a negative value instead. + */ + private double readCpuFreq(SystemInfo sysInfo) { + /* + * Try to read from the /sys/devices file first. If that doesn't work + * try manually inspecting the /proc/cpuinfo file. + */ + long cpuFreqKhz = sysInfo + .readLongFromFile("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"); + if (cpuFreqKhz != -1) { + return cpuFreqKhz / 1000.0; + } + + FileReader fstream; + try { + fstream = new FileReader(CPU_FREQ_FILE); + } catch (FileNotFoundException e) { + Log.w(TAG, "Could not read cpu frequency file"); + return -1; + } + BufferedReader in = new BufferedReader(fstream, 500); + String line; + try { + while ((line = in.readLine()) != null) { + if (line.startsWith("BogoMIPS")) { + in.close(); + return Double.parseDouble(line.trim().split("[ :]+")[1]); + } + } + in.close(); + } catch (IOException e) { + /* Failed to read from the cpu freq file. */ + } catch (NumberFormatException e) { + /* Frequency not formatted properly as a double. */ + } + Log.w(TAG, "Failed to read cpu frequency"); + return -1; + } +} diff --git a/src/edu/umich/PowerTutor/components/GPS.java b/src/com/henny/PowerTutor2/components/GPS.java similarity index 94% rename from src/edu/umich/PowerTutor/components/GPS.java rename to src/com/henny/PowerTutor2/components/GPS.java index c350819..b6d32fb 100644 --- a/src/edu/umich/PowerTutor/components/GPS.java +++ b/src/com/henny/PowerTutor2/components/GPS.java @@ -14,19 +14,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.components; - -import edu.umich.PowerTutor.PowerNotifications; -import edu.umich.PowerTutor.phone.PhoneConstants; -import edu.umich.PowerTutor.service.IterationData; -import edu.umich.PowerTutor.service.PowerData; -import edu.umich.PowerTutor.util.NotificationService; -import edu.umich.PowerTutor.util.Recycler; -import edu.umich.PowerTutor.util.SystemInfo; +package com.henny.PowerTutor2.components; +import com.henny.PowerTutor2.PowerNotifications; import android.content.Context; import android.location.GpsSatellite; import android.location.GpsStatus; @@ -44,6 +36,13 @@ import java.lang.reflect.Type; import java.util.Map; +import com.henny.PowerTutor2.phone.PhoneConstants; +import com.henny.PowerTutor2.service.IterationData; +import com.henny.PowerTutor2.service.PowerData; +import com.henny.PowerTutor2.util.NotificationService; +import com.henny.PowerTutor2.util.Recycler; +import com.henny.PowerTutor2.util.SystemInfo; + public class GPS extends PowerComponent { public static class GpsData extends PowerData { private static Recycler recycler = new Recycler(); @@ -230,6 +229,7 @@ public void run() { event = fin.read()) { gpsState.updateEvent(event, HOOK_LIBGPS); } + fin.close(); } catch(IOException e) { e.printStackTrace(); } diff --git a/src/edu/umich/PowerTutor/components/LCD.java b/src/com/henny/PowerTutor2/components/LCD.java similarity index 88% rename from src/edu/umich/PowerTutor/components/LCD.java rename to src/com/henny/PowerTutor2/components/LCD.java index 869cd59..20120b3 100644 --- a/src/edu/umich/PowerTutor/components/LCD.java +++ b/src/com/henny/PowerTutor2/components/LCD.java @@ -13,20 +13,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . - -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.components; - -import edu.umich.PowerTutor.PowerNotifications; -import edu.umich.PowerTutor.service.IterationData; -import edu.umich.PowerTutor.service.PowerData; -import edu.umich.PowerTutor.util.ForegroundDetector; -import edu.umich.PowerTutor.util.NotificationService; -import edu.umich.PowerTutor.util.Recycler; -import edu.umich.PowerTutor.util.SystemInfo; +package com.henny.PowerTutor2.components; +import com.henny.PowerTutor2.PowerNotifications; import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; @@ -41,6 +32,13 @@ import java.io.OutputStreamWriter; import java.util.List; +import com.henny.PowerTutor2.service.IterationData; +import com.henny.PowerTutor2.service.PowerData; +import com.henny.PowerTutor2.util.ForegroundDetector; +import com.henny.PowerTutor2.util.NotificationService; +import com.henny.PowerTutor2.util.Recycler; +import com.henny.PowerTutor2.util.SystemInfo; + public class LCD extends PowerComponent { public static class LcdData extends PowerData { private static Recycler recycler = new Recycler(); diff --git a/src/edu/umich/PowerTutor/components/OLED.java b/src/com/henny/PowerTutor2/components/OLED.java similarity index 91% rename from src/edu/umich/PowerTutor/components/OLED.java rename to src/com/henny/PowerTutor2/components/OLED.java index 9987709..5ed7d7e 100644 --- a/src/edu/umich/PowerTutor/components/OLED.java +++ b/src/com/henny/PowerTutor2/components/OLED.java @@ -14,21 +14,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.components; - -import edu.umich.PowerTutor.PowerNotifications; -import edu.umich.PowerTutor.phone.PhoneConstants; -import edu.umich.PowerTutor.service.IterationData; -import edu.umich.PowerTutor.service.PowerData; -import edu.umich.PowerTutor.util.NativeLoader; -import edu.umich.PowerTutor.util.NotificationService; -import edu.umich.PowerTutor.util.Recycler; -import edu.umich.PowerTutor.util.SystemInfo; -import edu.umich.PowerTutor.util.ForegroundDetector; +package com.henny.PowerTutor2.components; +import com.henny.PowerTutor2.PowerNotifications; import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; @@ -49,11 +39,19 @@ import java.io.OutputStreamWriter; import java.util.List; import java.util.Random; - import java.io.*; import java.nio.*; import java.nio.channels.*; +import com.henny.PowerTutor2.phone.PhoneConstants; +import com.henny.PowerTutor2.service.IterationData; +import com.henny.PowerTutor2.service.PowerData; +import com.henny.PowerTutor2.util.ForegroundDetector; +import com.henny.PowerTutor2.util.NativeLoader; +import com.henny.PowerTutor2.util.NotificationService; +import com.henny.PowerTutor2.util.Recycler; +import com.henny.PowerTutor2.util.SystemInfo; + public class OLED extends PowerComponent { public static class OledData extends PowerData { private static Recycler recycler = new Recycler(); diff --git a/src/edu/umich/PowerTutor/components/PowerComponent.java b/src/com/henny/PowerTutor2/components/PowerComponent.java similarity index 96% rename from src/edu/umich/PowerTutor/components/PowerComponent.java rename to src/com/henny/PowerTutor2/components/PowerComponent.java index 0b6eadd..4d23827 100644 --- a/src/edu/umich/PowerTutor/components/PowerComponent.java +++ b/src/com/henny/PowerTutor2/components/PowerComponent.java @@ -14,12 +14,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.components; +package com.henny.PowerTutor2.components; -import edu.umich.PowerTutor.service.IterationData; +import com.henny.PowerTutor2.service.IterationData; import android.os.SystemClock; import android.util.Log; diff --git a/src/edu/umich/PowerTutor/components/Sensors.java b/src/com/henny/PowerTutor2/components/Sensors.java similarity index 89% rename from src/edu/umich/PowerTutor/components/Sensors.java rename to src/com/henny/PowerTutor2/components/Sensors.java index e0917fb..5887e06 100644 --- a/src/edu/umich/PowerTutor/components/Sensors.java +++ b/src/com/henny/PowerTutor2/components/Sensors.java @@ -1,6 +1,6 @@ /* +/* Copyright (C) 2011 The University of Michigan - 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 @@ -14,18 +14,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.components; - -import edu.umich.PowerTutor.PowerNotifications; -import edu.umich.PowerTutor.service.IterationData; -import edu.umich.PowerTutor.service.PowerData; -import edu.umich.PowerTutor.util.NotificationService; -import edu.umich.PowerTutor.util.Recycler; -import edu.umich.PowerTutor.util.SystemInfo; +package com.henny.PowerTutor2.components; +import com.henny.PowerTutor2.PowerNotifications; import android.content.Context; import android.hardware.SensorManager; import android.os.SystemClock; @@ -34,10 +27,11 @@ import java.io.IOException; import java.io.OutputStreamWriter; -import java.util.Set; -import java.util.TreeSet; -import java.util.Map; -import java.util.TreeMap; + +import com.henny.PowerTutor2.service.IterationData; +import com.henny.PowerTutor2.service.PowerData; +import com.henny.PowerTutor2.util.NotificationService; +import com.henny.PowerTutor2.util.Recycler; public class Sensors extends PowerComponent { private final String TAG = "Sensors"; diff --git a/src/edu/umich/PowerTutor/components/Threeg.java b/src/com/henny/PowerTutor2/components/Threeg.java similarity index 93% rename from src/edu/umich/PowerTutor/components/Threeg.java rename to src/com/henny/PowerTutor2/components/Threeg.java index 88d8736..f7f4c11 100644 --- a/src/edu/umich/PowerTutor/components/Threeg.java +++ b/src/com/henny/PowerTutor2/components/Threeg.java @@ -14,17 +14,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.components; - -import edu.umich.PowerTutor.phone.PhoneConstants; -import edu.umich.PowerTutor.service.IterationData; -import edu.umich.PowerTutor.service.PowerData; -import edu.umich.PowerTutor.service.PowerEstimator; -import edu.umich.PowerTutor.util.Recycler; -import edu.umich.PowerTutor.util.SystemInfo; +package com.henny.PowerTutor2.components; import android.content.Context; import android.os.SystemClock; @@ -32,13 +24,16 @@ import android.util.SparseArray; import android.telephony.TelephonyManager; -import java.io.BufferedReader; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; -import java.io.RandomAccessFile; + +import com.henny.PowerTutor2.phone.PhoneConstants; +import com.henny.PowerTutor2.service.IterationData; +import com.henny.PowerTutor2.service.PowerData; +import com.henny.PowerTutor2.service.PowerEstimator; +import com.henny.PowerTutor2.util.Recycler; +import com.henny.PowerTutor2.util.SystemInfo; public class Threeg extends PowerComponent { public static class ThreegData extends PowerData { diff --git a/src/com/henny/PowerTutor2/components/Wifi.java b/src/com/henny/PowerTutor2/components/Wifi.java new file mode 100644 index 0000000..496d0e7 --- /dev/null +++ b/src/com/henny/PowerTutor2/components/Wifi.java @@ -0,0 +1,454 @@ +/* +Copyright (C) 2011 The University of Michigan + +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 . + + */ + +package com.henny.PowerTutor2.components; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStreamWriter; + +import com.henny.PowerTutor2.phone.PhoneConstants; +import com.henny.PowerTutor2.service.IterationData; +import com.henny.PowerTutor2.service.PowerData; +import com.henny.PowerTutor2.util.Recycler; +import com.henny.PowerTutor2.util.SystemInfo; + +import android.content.Context; +import android.net.wifi.WifiManager; +import android.os.SystemClock; +import android.util.Log; +import android.util.SparseArray; + +public class Wifi extends PowerComponent { + public static class WifiData extends PowerData { + private static Recycler recycler = new Recycler(); + + public static WifiData obtain() { + + WifiData result = recycler.obtain(); + if (result != null) + return result; + return new WifiData(); + } + + @Override + public void recycle() { + recycler.recycle(this); + } + + public boolean wifiOn; + public double packets; + public long uplinkBytes; + public long downlinkBytes; + public double uplinkRate; + public double linkSpeed; + public int powerState; + + private WifiData() { + } + + public void init(double packets, long uplinkBytes, long downlinkBytes, + double uplinkRate, double linkSpeed, int powerState) { + wifiOn = true; + this.packets = packets; + this.uplinkBytes = uplinkBytes; + this.downlinkBytes = downlinkBytes; + this.uplinkRate = uplinkRate; + this.linkSpeed = linkSpeed; + this.powerState = powerState; + } + + public void init() { + wifiOn = false; + } + + public void writeLogDataInfo(OutputStreamWriter out) throws IOException { + StringBuilder res = new StringBuilder(); + res.append("Wifi-on ").append(wifiOn).append("\n"); + if (wifiOn) { + res.append("Wifi-packets ").append((long) Math.round(packets)) + .append("\nWifi-uplinkBytes ").append(uplinkBytes) + .append("\nWifi-downlinkBytes ").append(downlinkBytes) + .append("\nWifi-uplink ") + .append((long) Math.round(uplinkRate)) + .append("\nWifi-speed ") + .append((long) Math.round(linkSpeed)) + .append("\nWifi-state ") + .append(Wifi.POWER_STATE_NAMES[powerState]) + .append("\n"); + } + out.write(res.toString()); + } + } + + public static final int POWER_STATE_LOW = 0; + public static final int POWER_STATE_HIGH = 1; + public static final String[] POWER_STATE_NAMES = { "LOW", "HIGH" }; + + private static final String TAG = "Wifi"; + + private PhoneConstants phoneConstants; + private WifiManager wifiManager; + private SystemInfo sysInfo; + + private long lastLinkSpeed; + private int[] lastUids; + private WifiStateKeeper wifiState; + private SparseArray uidStates; + + private String transPacketsFile; + private String readPacketsFile; + private String transBytesFile; + private String readBytesFile; + private File uidStatsFolder; + private String interfaceName; + + public Wifi(Context context, PhoneConstants phoneConstants) { + this.phoneConstants = phoneConstants; + wifiManager = (WifiManager) context + .getSystemService(Context.WIFI_SERVICE); + sysInfo = SystemInfo.getInstance(); + + /* + * Try to grab the interface name. If we can't find it will take a wild + * stab in the dark. + */ + interfaceName = SystemInfo.getInstance().getProperty("wifi.interface"); + if (interfaceName == null) + interfaceName = "eth0"; + + lastLinkSpeed = -1; + wifiState = new WifiStateKeeper(phoneConstants.wifiHighLowTransition(), + phoneConstants.wifiLowHighTransition()); + uidStates = new SparseArray(); + + changeWifiDirectory("/sys/devices/virtual/net/"); + + uidStatsFolder = new File("/proc/uid_stat"); + } + + private void changeWifiDirectory(String prefix) { + transPacketsFile = prefix + interfaceName + "/statistics/tx_packets"; + readPacketsFile = prefix + interfaceName + "/statistics/rx_packets"; + transBytesFile = prefix + interfaceName + "/statistics/tx_bytes"; + readBytesFile = prefix + interfaceName + "/statistics/rx_bytes"; + } + + @Override + public IterationData calculateIteration(long iteration) { + IterationData result = IterationData.obtain(); + + int wifiStateFlag = wifiManager.getWifiState(); + if (wifiStateFlag != WifiManager.WIFI_STATE_ENABLED + && wifiStateFlag != WifiManager.WIFI_STATE_DISABLING) { + /* + * We need to allow the real iterface state keeper to reset it's + * state so that the next update it knows it's coming back from an + * off state. We also need to clear all the uid information. + */ + wifiState.interfaceOff(); + uidStates.clear(); + lastLinkSpeed = -1; + + WifiData data = WifiData.obtain(); + data.init(); + result.setPowerData(data); + return result; + } + + long transmitPackets = sysInfo.readLongFromFile(transPacketsFile); + long receivePackets = sysInfo.readLongFromFile(readPacketsFile); + long transmitBytes = sysInfo.readLongFromFile(transBytesFile); + long receiveBytes = sysInfo.readLongFromFile(readBytesFile); + + if (transmitPackets == -1 || receivePackets == -1 + || transmitBytes == -1 || receiveBytes == -1) { + changeWifiDirectory("/sys/class/net/"); + + /* Couldn't read interface data files. */ + Log.w(TAG, + "Failed to read packet and byte counts from wifi interface"); + return result; + } + + /* + * Update the link speed every 15 seconds as pulling the WifiInfo + * structure from WifiManager is a little bit expensive. This isn't + * really something that is likely to change very frequently anyway. + */ + if (iteration % 15 == 0 || lastLinkSpeed == -1) { + lastLinkSpeed = wifiManager.getConnectionInfo().getLinkSpeed(); + } + double linkSpeed = lastLinkSpeed; + + if (wifiState.isInitialized()) { + wifiState.updateState(transmitPackets, receivePackets, + transmitBytes, receiveBytes); + WifiData data = WifiData.obtain(); + data.init(wifiState.getPackets(), wifiState.getUplinkBytes(), + wifiState.getDownlinkBytes(), wifiState.getUplinkRate(), + linkSpeed, wifiState.getPowerState()); + result.setPowerData(data); + } else { + wifiState.updateState(transmitPackets, receivePackets, + transmitBytes, receiveBytes); + } + + lastUids = sysInfo.getUids(lastUids); + if (lastUids != null) + for (int uid : lastUids) { + if (uid == -1) { + continue; + } + try { + WifiStateKeeper uidState = uidStates.get(uid); + if (uidState == null) { + uidState = new WifiStateKeeper( + phoneConstants.wifiHighLowTransition(), + phoneConstants.wifiLowHighTransition()); + uidStates.put(uid, uidState); + } + + if (!uidState.isStale()) { + /* + * We use a huerstic here so that we don't poll for uids + * that haven't had much activity recently. + */ + continue; + } + + /* These read operations are the expensive part of polling. */ + receiveBytes = sysInfo.readLongFromFile("/proc/uid_stat/" + + uid + "/tcp_rcv"); + transmitBytes = sysInfo.readLongFromFile("/proc/uid_stat/" + + uid + "/tcp_snd"); + + if (receiveBytes == -1 || transmitBytes == -1) { + Log.w(TAG, "Failed to read uid read/write byte counts"); + } else if (uidState.isInitialized()) { + /* + * We only have information about bytes received but + * what we really want is the number of packets received + * so we just have to estimate it. + */ + long deltaTransmitBytes = transmitBytes + - uidState.getTransmitBytes(); + long deltaReceiveBytes = receiveBytes + - uidState.getReceiveBytes(); + long estimatedTransmitPackets = (long) Math + .round(deltaTransmitBytes + / wifiState + .getAverageTransmitPacketSize()); + long estimatedReceivePackets = (long) Math + .round(deltaReceiveBytes + / wifiState + .getAverageReceivePacketSize()); + if (deltaTransmitBytes > 0 + && estimatedTransmitPackets == 0) { + estimatedTransmitPackets = 1; + } + if (deltaReceiveBytes > 0 + && estimatedReceivePackets == 0) { + estimatedReceivePackets = 1; + } + + boolean active = transmitBytes != uidState + .getTransmitBytes() + || receiveBytes != uidState.getReceiveBytes(); + uidState.updateState(uidState.getTransmitPackets() + + estimatedTransmitPackets, + uidState.getReceivePackets() + + estimatedReceivePackets, + transmitBytes, receiveBytes); + + if (active) { + WifiData uidData = WifiData.obtain(); + uidData.init(uidState.getPackets(), + uidState.getUplinkBytes(), + uidState.getDownlinkBytes(), + uidState.getUplinkRate(), linkSpeed, + uidState.getPowerState()); + result.addUidPowerData(uid, uidData); + } + } else { + uidState.updateState(0, 0, transmitBytes, receiveBytes); + } + } catch (NumberFormatException e) { + Log.w(TAG, "Non-uid files in /proc/uid_stat"); + } + } + + return result; + } + + private static class WifiStateKeeper { + private long lastTransmitPackets; + private long lastReceivePackets; + private long lastTransmitBytes; + private long lastReceiveBytes; + private long lastTime; + + private int powerState; + private double lastPackets; + private double lastUplinkRate; + private double lastAverageTransmitPacketSize; + private double lastAverageReceivePacketSize; + + private long deltaUplinkBytes; + private long deltaDownlinkBytes; + + private double highLowTransition; + private double lowHighTransition; + + private long inactiveTime; + + public WifiStateKeeper(double highLowTransition, + double lowHighTransition) { + this.highLowTransition = highLowTransition; + this.lowHighTransition = lowHighTransition; + lastTransmitPackets = lastReceivePackets = lastTransmitBytes = lastTime = -1; + powerState = POWER_STATE_LOW; + lastPackets = lastUplinkRate = 0; + lastAverageTransmitPacketSize = 1000; + lastAverageReceivePacketSize = 1000; + inactiveTime = 0; + } + + public void interfaceOff() { + lastTime = SystemClock.elapsedRealtime(); + powerState = POWER_STATE_LOW; + } + + public boolean isInitialized() { + return lastTime != -1; + } + + public void updateState(long transmitPackets, long receivePackets, + long transmitBytes, long receiveBytes) { + long curTime = SystemClock.elapsedRealtime(); + if (lastTime != -1 && curTime > lastTime) { + double deltaTime = curTime - lastTime; + lastUplinkRate = (transmitBytes - lastTransmitBytes) / 1024.0 + * 7.8125 / deltaTime; + lastPackets = receivePackets + transmitPackets + - lastReceivePackets - lastTransmitPackets; + deltaUplinkBytes = transmitBytes - lastTransmitBytes; + deltaDownlinkBytes = receiveBytes - lastReceiveBytes; + if (transmitPackets != lastTransmitPackets) { + lastAverageTransmitPacketSize = 0.9 + * lastAverageTransmitPacketSize + 0.1 + * (transmitBytes - lastTransmitBytes) + / (transmitPackets - lastTransmitPackets); + } + if (receivePackets != lastReceivePackets) { + lastAverageReceivePacketSize = 0.9 + * lastAverageReceivePacketSize + 0.1 + * (receiveBytes - lastReceiveBytes) + / (receivePackets - lastReceivePackets); + } + + if (receiveBytes != lastReceiveBytes + || transmitBytes != lastTransmitBytes) { + inactiveTime = 0; + } else { + inactiveTime += curTime - lastTime; + } + + if (lastPackets < highLowTransition) { + powerState = POWER_STATE_LOW; + } else if (lastPackets > lowHighTransition) { + powerState = POWER_STATE_HIGH; + } + } + lastTime = curTime; + lastTransmitPackets = transmitPackets; + lastReceivePackets = receivePackets; + lastTransmitBytes = transmitBytes; + lastReceiveBytes = receiveBytes; + } + + public int getPowerState() { + return powerState; + } + + public double getPackets() { + return lastPackets; + } + + public long getUplinkBytes() { + return deltaUplinkBytes; + } + + public long getDownlinkBytes() { + return deltaDownlinkBytes; + } + + public double getUplinkRate() { + return lastUplinkRate; + } + + public double getAverageTransmitPacketSize() { + return lastAverageTransmitPacketSize; + } + + public double getAverageReceivePacketSize() { + return lastAverageReceivePacketSize; + } + + public long getTransmitPackets() { + return lastTransmitPackets; + } + + public long getReceivePackets() { + return lastReceivePackets; + } + + public long getTransmitBytes() { + return lastTransmitBytes; + } + + public long getReceiveBytes() { + return lastReceiveBytes; + } + + /* + * The idea here is that we don't want to have to read uid information + * every single iteration for each uid as it just takes too long. So + * here we are designing a hueristic that helps us avoid polling for too + * many uids. + */ + public boolean isStale() { + long curTime = SystemClock.elapsedRealtime(); + return curTime - lastTime > (long) Math.min(10000, inactiveTime); + } + } + + private long readLongFromFile(String filePath) { + return sysInfo.readLongFromFile(filePath); + } + + @Override + public boolean hasUidInformation() { + return uidStatsFolder.exists(); + } + + @Override + public String getComponentName() { + return "Wifi"; + } +} diff --git a/src/edu/umich/PowerTutor/phone/DreamConstants.java b/src/com/henny/PowerTutor2/phone/DreamConstants.java similarity index 97% rename from src/edu/umich/PowerTutor/phone/DreamConstants.java rename to src/com/henny/PowerTutor2/phone/DreamConstants.java index bf99925..1b44548 100644 --- a/src/edu/umich/PowerTutor/phone/DreamConstants.java +++ b/src/com/henny/PowerTutor2/phone/DreamConstants.java @@ -14,17 +14,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.phone; +package com.henny.PowerTutor2.phone; + +import com.henny.PowerTutor2.components.Sensors; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorManager; -import edu.umich.PowerTutor.components.Sensors; - public class DreamConstants implements PhoneConstants { protected static final String OPER_TMOBILE = "T - Mobile"; protected static final String OPER_ATT = "AT&T"; diff --git a/src/edu/umich/PowerTutor/phone/DreamPowerCalculator.java b/src/com/henny/PowerTutor2/phone/DreamPowerCalculator.java similarity index 89% rename from src/edu/umich/PowerTutor/phone/DreamPowerCalculator.java rename to src/com/henny/PowerTutor2/phone/DreamPowerCalculator.java index 2248026..f1e6283 100644 --- a/src/edu/umich/PowerTutor/phone/DreamPowerCalculator.java +++ b/src/com/henny/PowerTutor2/phone/DreamPowerCalculator.java @@ -14,20 +14,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.phone; - -import edu.umich.PowerTutor.components.*; -import edu.umich.PowerTutor.components.LCD.LcdData; -import edu.umich.PowerTutor.components.OLED.OledData; -import edu.umich.PowerTutor.components.CPU.CpuData; -import edu.umich.PowerTutor.components.Audio.AudioData; -import edu.umich.PowerTutor.components.GPS.GpsData; -import edu.umich.PowerTutor.components.Wifi.WifiData; -import edu.umich.PowerTutor.components.Threeg.ThreegData; -import edu.umich.PowerTutor.components.Sensors.SensorData; +package com.henny.PowerTutor2.phone; + +import com.henny.PowerTutor2.components.*; +import com.henny.PowerTutor2.components.Audio.AudioData; +import com.henny.PowerTutor2.components.CPU.CpuData; +import com.henny.PowerTutor2.components.GPS.GpsData; +import com.henny.PowerTutor2.components.LCD.LcdData; +import com.henny.PowerTutor2.components.OLED.OledData; +import com.henny.PowerTutor2.components.Sensors.SensorData; +import com.henny.PowerTutor2.components.Threeg.ThreegData; +import com.henny.PowerTutor2.components.Wifi.WifiData; import android.content.Context; diff --git a/src/edu/umich/PowerTutor/phone/PassionConstants.java b/src/com/henny/PowerTutor2/phone/PassionConstants.java similarity index 98% rename from src/edu/umich/PowerTutor/phone/PassionConstants.java rename to src/com/henny/PowerTutor2/phone/PassionConstants.java index c525bce..a1c2a18 100644 --- a/src/edu/umich/PowerTutor/phone/PassionConstants.java +++ b/src/com/henny/PowerTutor2/phone/PassionConstants.java @@ -14,10 +14,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.phone; +package com.henny.PowerTutor2.phone; import android.content.Context; import android.util.DisplayMetrics; diff --git a/src/edu/umich/PowerTutor/phone/PassionPowerCalculator.java b/src/com/henny/PowerTutor2/phone/PassionPowerCalculator.java similarity index 78% rename from src/edu/umich/PowerTutor/phone/PassionPowerCalculator.java rename to src/com/henny/PowerTutor2/phone/PassionPowerCalculator.java index 3ab78b2..d93716d 100644 --- a/src/edu/umich/PowerTutor/phone/PassionPowerCalculator.java +++ b/src/com/henny/PowerTutor2/phone/PassionPowerCalculator.java @@ -17,15 +17,15 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.phone; - -import edu.umich.PowerTutor.components.LCD.LcdData; -import edu.umich.PowerTutor.components.OLED.OledData; -import edu.umich.PowerTutor.components.CPU.CpuData; -import edu.umich.PowerTutor.components.Audio.AudioData; -import edu.umich.PowerTutor.components.GPS.GpsData; -import edu.umich.PowerTutor.components.Wifi.WifiData; -import edu.umich.PowerTutor.components.Threeg.ThreegData; +package com.henny.PowerTutor2.phone; + +import com.henny.PowerTutor2.components.Audio.AudioData; +import com.henny.PowerTutor2.components.CPU.CpuData; +import com.henny.PowerTutor2.components.GPS.GpsData; +import com.henny.PowerTutor2.components.LCD.LcdData; +import com.henny.PowerTutor2.components.OLED.OledData; +import com.henny.PowerTutor2.components.Threeg.ThreegData; +import com.henny.PowerTutor2.components.Wifi.WifiData; import android.content.Context; diff --git a/src/edu/umich/PowerTutor/phone/PhoneConstants.java b/src/com/henny/PowerTutor2/phone/PhoneConstants.java similarity index 99% rename from src/edu/umich/PowerTutor/phone/PhoneConstants.java rename to src/com/henny/PowerTutor2/phone/PhoneConstants.java index 73b1950..7f657d8 100644 --- a/src/edu/umich/PowerTutor/phone/PhoneConstants.java +++ b/src/com/henny/PowerTutor2/phone/PhoneConstants.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.phone; +package com.henny.PowerTutor2.phone; public interface PhoneConstants { /* Return the name of the model represented by these constants diff --git a/src/edu/umich/PowerTutor/phone/PhonePowerCalculator.java b/src/com/henny/PowerTutor2/phone/PhonePowerCalculator.java similarity index 70% rename from src/edu/umich/PowerTutor/phone/PhonePowerCalculator.java rename to src/com/henny/PowerTutor2/phone/PhonePowerCalculator.java index addcfe1..c694a70 100644 --- a/src/edu/umich/PowerTutor/phone/PhonePowerCalculator.java +++ b/src/com/henny/PowerTutor2/phone/PhonePowerCalculator.java @@ -17,16 +17,16 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.phone; - -import edu.umich.PowerTutor.components.LCD.LcdData; -import edu.umich.PowerTutor.components.OLED.OledData; -import edu.umich.PowerTutor.components.CPU.CpuData; -import edu.umich.PowerTutor.components.Audio.AudioData; -import edu.umich.PowerTutor.components.GPS.GpsData; -import edu.umich.PowerTutor.components.Wifi.WifiData; -import edu.umich.PowerTutor.components.Threeg.ThreegData; -import edu.umich.PowerTutor.components.Sensors.SensorData; +package com.henny.PowerTutor2.phone; + +import com.henny.PowerTutor2.components.Audio.AudioData; +import com.henny.PowerTutor2.components.CPU.CpuData; +import com.henny.PowerTutor2.components.GPS.GpsData; +import com.henny.PowerTutor2.components.LCD.LcdData; +import com.henny.PowerTutor2.components.OLED.OledData; +import com.henny.PowerTutor2.components.Sensors.SensorData; +import com.henny.PowerTutor2.components.Threeg.ThreegData; +import com.henny.PowerTutor2.components.Wifi.WifiData; public interface PhonePowerCalculator { public double getLcdPower(LcdData data); diff --git a/src/com/henny/PowerTutor2/phone/PhoneSelector.java b/src/com/henny/PowerTutor2/phone/PhoneSelector.java new file mode 100644 index 0000000..881a6e0 --- /dev/null +++ b/src/com/henny/PowerTutor2/phone/PhoneSelector.java @@ -0,0 +1,209 @@ +/* +Copyright (C) 2011 The University of Michigan + +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 . + +Please send inquiries to powertutor@umich.edu + */ + +package com.henny.PowerTutor2.phone; + +import java.util.List; + +import com.henny.PowerTutor2.components.Audio; +import com.henny.PowerTutor2.components.CPU; +import com.henny.PowerTutor2.components.GPS; +import com.henny.PowerTutor2.components.LCD; +import com.henny.PowerTutor2.components.OLED; +import com.henny.PowerTutor2.components.PowerComponent; +import com.henny.PowerTutor2.components.Sensors; +import com.henny.PowerTutor2.components.Threeg; +import com.henny.PowerTutor2.components.Wifi; +import com.henny.PowerTutor2.components.Audio.AudioData; +import com.henny.PowerTutor2.components.CPU.CpuData; +import com.henny.PowerTutor2.components.GPS.GpsData; +import com.henny.PowerTutor2.components.LCD.LcdData; +import com.henny.PowerTutor2.components.OLED.OledData; +import com.henny.PowerTutor2.components.Sensors.SensorData; +import com.henny.PowerTutor2.components.Threeg.ThreegData; +import com.henny.PowerTutor2.components.Wifi.WifiData; +import com.henny.PowerTutor2.service.PowerData; +import com.henny.PowerTutor2.util.NotificationService; +import com.henny.PowerTutor2.util.SystemInfo; + +import android.content.Context; +import android.os.Build; +import android.util.Log; + +public class PhoneSelector { + private static final String TAG = "PhoneSelector"; + + public static final int PHONE_UNKNOWN = 0; + public static final int PHONE_DREAM = 1; /* G1 */ + public static final int PHONE_SAPPHIRE = 2; /* G2 */ + public static final int PHONE_PASSION = 3; /* Nexus One */ + + /* A hard-coded list of phones that have OLED screens. */ + public static final String[] OLED_PHONES = { "bravo", "passion", + "GT-I9000", "inc", "legend", "GT-I7500", "SPH-M900", "SGH-I897", + "SGH-T959", "desirec", }; + + /* + * This class is not supposed to be instantiated. Just use the static + * members. + */ + private PhoneSelector() { + } + + public static boolean phoneSupported() { + return getPhoneType() != PHONE_UNKNOWN; + } + + public static boolean hasOled() { + for (int i = 0; i < OLED_PHONES.length; i++) { + if (Build.DEVICE.equals(OLED_PHONES[i])) { + return true; + } + } + return false; + } + + public static int getPhoneType() { + if (Build.DEVICE.startsWith("dream")) + return PHONE_DREAM; + if (Build.DEVICE.startsWith("sapphire")) + return PHONE_SAPPHIRE; + if (Build.DEVICE.startsWith("passion")) + return PHONE_PASSION; + return PHONE_UNKNOWN; + } + + public static PhoneConstants getConstants(Context context) { + switch (getPhoneType()) { + case PHONE_DREAM: + return new DreamConstants(context); + case PHONE_SAPPHIRE: + return new SapphireConstants(context); + case PHONE_PASSION: + return new PassionConstants(context); + default: + boolean oled = hasOled(); + Log.w(TAG, "Phone type not recognized (" + Build.DEVICE + + "), using " + (oled ? "Passion" : "Dream") + " constants"); + return oled ? new PassionConstants(context) : new DreamConstants( + context); + } + } + + public static PhonePowerCalculator getCalculator(Context context) { + switch (getPhoneType()) { + case PHONE_DREAM: + return new DreamPowerCalculator(context); + case PHONE_SAPPHIRE: + return new SapphirePowerCalculator(context); + case PHONE_PASSION: + return new PassionPowerCalculator(context); + default: + boolean oled = hasOled(); + Log.w(TAG, "Phone type not recognized (" + Build.DEVICE + + "), using " + (oled ? "Passion" : "Dream") + + " calculator"); + return oled ? new PassionPowerCalculator(context) + : new DreamPowerCalculator(context); + } + } + + public static void generateComponents(Context context, + List components, List functions) { + final PhoneConstants constants = getConstants(context); + final PhonePowerCalculator calculator = getCalculator(context); + + // TODO: What about bluetooth? + // TODO: LED light on the Nexus + + /* Add display component. */ + if (hasOled()) { + components.add(new OLED(context, constants)); + functions.add(new PowerFunction() { + public double calculate(PowerData data) { + return calculator.getOledPower((OledData) data); + } + }); + } else { + components.add(new LCD(context)); + functions.add(new PowerFunction() { + public double calculate(PowerData data) { + return calculator.getLcdPower((LcdData) data); + } + }); + } + + /* Add CPU component. */ + components.add(new CPU(constants)); + functions.add(new PowerFunction() { + public double calculate(PowerData data) { + return calculator.getCpuPower((CpuData) data); + } + }); + + /* Add Wifi component. */ + String wifiInterface = ""; + wifiInterface = SystemInfo.getInstance().getProperty("wifi.interface"); + + if (wifiInterface != null && wifiInterface.length() != 0) { + components.add(new Wifi(context, constants)); + functions.add(new PowerFunction() { + public double calculate(PowerData data) { + return calculator.getWifiPower((WifiData) data); + } + }); + } + + /* Add 3G component. */ + if (constants.threegInterface().length() != 0) { + components.add(new Threeg(context, constants)); + functions.add(new PowerFunction() { + public double calculate(PowerData data) { + return calculator.getThreeGPower((ThreegData) data); + } + }); + } + + /* Add GPS component. */ + components.add(new GPS(context, constants)); + functions.add(new PowerFunction() { + public double calculate(PowerData data) { + return calculator.getGpsPower((GpsData) data); + } + }); + + /* Add Audio component. */ + components.add(new Audio(context)); + functions.add(new PowerFunction() { + public double calculate(PowerData data) { + return calculator.getAudioPower((AudioData) data); + } + }); + + /* Add Sensors component if avaialble. */ + if (NotificationService.available()) { + components.add(new Sensors(context)); + functions.add(new PowerFunction() { + public double calculate(PowerData data) { + return calculator.getSensorPower((SensorData) data); + } + }); + } + } +} diff --git a/src/edu/umich/PowerTutor/phone/PowerFunction.java b/src/com/henny/PowerTutor2/phone/PowerFunction.java similarity index 90% rename from src/edu/umich/PowerTutor/phone/PowerFunction.java rename to src/com/henny/PowerTutor2/phone/PowerFunction.java index d32e467..8efea13 100644 --- a/src/edu/umich/PowerTutor/phone/PowerFunction.java +++ b/src/com/henny/PowerTutor2/phone/PowerFunction.java @@ -17,9 +17,9 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.phone; +package com.henny.PowerTutor2.phone; -import edu.umich.PowerTutor.service.PowerData; +import com.henny.PowerTutor2.service.PowerData; public interface PowerFunction { public double calculate(PowerData data); diff --git a/src/edu/umich/PowerTutor/phone/SapphireConstants.java b/src/com/henny/PowerTutor2/phone/SapphireConstants.java similarity index 98% rename from src/edu/umich/PowerTutor/phone/SapphireConstants.java rename to src/com/henny/PowerTutor2/phone/SapphireConstants.java index c0045cd..53eb5e1 100644 --- a/src/edu/umich/PowerTutor/phone/SapphireConstants.java +++ b/src/com/henny/PowerTutor2/phone/SapphireConstants.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.phone; +package com.henny.PowerTutor2.phone; import android.content.Context; diff --git a/src/edu/umich/PowerTutor/phone/SapphirePowerCalculator.java b/src/com/henny/PowerTutor2/phone/SapphirePowerCalculator.java similarity index 75% rename from src/edu/umich/PowerTutor/phone/SapphirePowerCalculator.java rename to src/com/henny/PowerTutor2/phone/SapphirePowerCalculator.java index b390ce1..5354046 100644 --- a/src/edu/umich/PowerTutor/phone/SapphirePowerCalculator.java +++ b/src/com/henny/PowerTutor2/phone/SapphirePowerCalculator.java @@ -17,14 +17,14 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.phone; - -import edu.umich.PowerTutor.components.LCD.LcdData; -import edu.umich.PowerTutor.components.CPU.CpuData; -import edu.umich.PowerTutor.components.Audio.AudioData; -import edu.umich.PowerTutor.components.GPS.GpsData; -import edu.umich.PowerTutor.components.Wifi.WifiData; -import edu.umich.PowerTutor.components.Threeg.ThreegData; +package com.henny.PowerTutor2.phone; + +import com.henny.PowerTutor2.components.Audio.AudioData; +import com.henny.PowerTutor2.components.CPU.CpuData; +import com.henny.PowerTutor2.components.GPS.GpsData; +import com.henny.PowerTutor2.components.LCD.LcdData; +import com.henny.PowerTutor2.components.Threeg.ThreegData; +import com.henny.PowerTutor2.components.Wifi.WifiData; import android.content.Context; diff --git a/src/edu/umich/PowerTutor/service/ICounterService.aidl b/src/com/henny/PowerTutor2/service/ICounterService.aidl similarity index 95% rename from src/edu/umich/PowerTutor/service/ICounterService.aidl rename to src/com/henny/PowerTutor2/service/ICounterService.aidl index 96e5b38..199de2b 100644 --- a/src/edu/umich/PowerTutor/service/ICounterService.aidl +++ b/src/com/henny/PowerTutor2/service/ICounterService.aidl @@ -14,10 +14,9 @@ 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 . -Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.service; +package com.henny.PowerTutor2.service; interface ICounterService { // Returns the name of the components that are being logged. diff --git a/src/edu/umich/PowerTutor/service/IterationData.java b/src/com/henny/PowerTutor2/service/IterationData.java similarity index 94% rename from src/edu/umich/PowerTutor/service/IterationData.java rename to src/com/henny/PowerTutor2/service/IterationData.java index db75bb9..927f17c 100644 --- a/src/edu/umich/PowerTutor/service/IterationData.java +++ b/src/com/henny/PowerTutor2/service/IterationData.java @@ -17,10 +17,10 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.service; +package com.henny.PowerTutor2.service; -import edu.umich.PowerTutor.util.Recycler; -import edu.umich.PowerTutor.util.SystemInfo; +import com.henny.PowerTutor2.util.Recycler; +import com.henny.PowerTutor2.util.SystemInfo; import android.util.SparseArray; diff --git a/src/edu/umich/PowerTutor/service/LogUploader.java b/src/com/henny/PowerTutor2/service/LogUploader.java similarity index 95% rename from src/edu/umich/PowerTutor/service/LogUploader.java rename to src/com/henny/PowerTutor2/service/LogUploader.java index b07f542..9ce408d 100644 --- a/src/edu/umich/PowerTutor/service/LogUploader.java +++ b/src/com/henny/PowerTutor2/service/LogUploader.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.service; +package com.henny.PowerTutor2.service; import android.content.Context; diff --git a/src/edu/umich/PowerTutor/service/PowerData.java b/src/com/henny/PowerTutor2/service/PowerData.java similarity index 92% rename from src/edu/umich/PowerTutor/service/PowerData.java rename to src/com/henny/PowerTutor2/service/PowerData.java index 2033518..86cf74d 100644 --- a/src/edu/umich/PowerTutor/service/PowerData.java +++ b/src/com/henny/PowerTutor2/service/PowerData.java @@ -17,11 +17,10 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.service; +package com.henny.PowerTutor2.service; import java.io.OutputStreamWriter; import java.io.IOException; -import java.util.Vector; public abstract class PowerData { private int cachedPower; diff --git a/src/com/henny/PowerTutor2/service/PowerEstimator.java b/src/com/henny/PowerTutor2/service/PowerEstimator.java new file mode 100644 index 0000000..919f7af --- /dev/null +++ b/src/com/henny/PowerTutor2/service/PowerEstimator.java @@ -0,0 +1,733 @@ +/* +Copyright (C) 2011 The University of Michigan + +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 . + +Please send inquiries to powertutor@umich.edu + */ + +package com.henny.PowerTutor2.service; + +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.os.SystemClock; +import android.preference.PreferenceManager; +import android.provider.Settings; +import android.util.Log; +import android.util.SparseArray; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; + +import com.henny.PowerTutor2.components.CPU; +import com.henny.PowerTutor2.components.OLED; +import com.henny.PowerTutor2.components.PowerComponent; +import com.henny.PowerTutor2.phone.PhoneConstants; +import com.henny.PowerTutor2.phone.PhoneSelector; +import com.henny.PowerTutor2.phone.PowerFunction; +import com.henny.PowerTutor2.util.BatteryStats; +import com.henny.PowerTutor2.util.Counter; +import com.henny.PowerTutor2.util.HistoryBuffer; +import com.henny.PowerTutor2.util.NotificationService; +import com.henny.PowerTutor2.util.SystemInfo; +import com.henny.PowerTutor2.widget.PowerWidget; + +/** + * This class is responsible for starting the individual power component loggers + * (CPU, GPS, etc...) and collecting the information they generate. This + * information is used both to write a log file that will be send back to + * spidermoneky (or looked at by the user) and to implement the ICounterService + * IPC interface. + */ +public class PowerEstimator implements Runnable { + private static final String TAG = "PowerEstimator"; + + /* + * A dictionary used to assist in compression of the log files. Strings that + * appear more frequently should be put towards the end of the dictionary. + * It is not critical that every string that be written to the log appear + * here. + */ + private static final String DEFLATE_DICTIONARY = "onoffidleoff-hookringinglowairplane-modebatteryedgeGPRS3Gunknown" + + "in-serviceemergency-onlyout-of-servicepower-offdisconnectedconnecting" + + "associateconnectedsuspendedphone-callservicenetworkbegin.0123456789" + + "GPSAudioWifi3GLCDCPU-power "; + + public static final int ALL_COMPONENTS = -1; + public static final int ITERATION_INTERVAL = 1000; // 1 second + + private UMLoggerService context; + private SharedPreferences prefs; + // private boolean plugged; + + private Vector powerComponents; + private Vector powerFunctions; + private Vector histories; + private Map uidAppIds; + + // Miscellaneous data. + private HistoryBuffer oledScoreHistory; + + private Object fileWriteLock = new Object(); + private LogUploader logUploader; + private OutputStreamWriter logStream; + private DeflaterOutputStream deflateStream; + + private Object iterationLock = new Object(); + private long lastWrittenIteration; + + public PowerEstimator(UMLoggerService context) { + this.context = context; + prefs = PreferenceManager.getDefaultSharedPreferences(context); + + powerComponents = new Vector(); + powerFunctions = new Vector(); + uidAppIds = new HashMap(); + PhoneSelector.generateComponents(context, powerComponents, + powerFunctions); + + histories = new Vector(); + for (int i = 0; i < powerComponents.size(); i++) { + histories.add(new HistoryBuffer(300)); + } + oledScoreHistory = new HistoryBuffer(0); + + logUploader = new LogUploader(context); + openLog(true); + } + + private void openLog(boolean init) { + /* Open up the log file if possible. */ + try { + Log.i(TAG, "openLog"); + String logFilename = context.getFileStreamPath("PowerTrace.log") + .getAbsolutePath(); + + if (init && prefs.getBoolean("sendPermission", true) + && new File(logFilename).length() > 0) { + /* + * There is data to send. Make sure that gets going in the + * sending process before we write over any old logs. + */ + logUploader.upload(logFilename); + } + Deflater deflater = new Deflater(); + deflater.setDictionary(DEFLATE_DICTIONARY.getBytes()); + deflateStream = new DeflaterOutputStream(new FileOutputStream( + logFilename)); + logStream = new OutputStreamWriter(deflateStream); + } catch (IOException e) { + logStream = null; + Log.e(TAG, "Failed to open log file. No log will be kept."); + } + } + + /** + * This is the loop that keeps updating the power profile + */ + public void run() { + SystemInfo sysInfo = SystemInfo.getInstance(); + PackageManager pm = context.getPackageManager(); + BatteryStats bst = BatteryStats.getInstance(); + + int components = powerComponents.size(); + long beginTime = SystemClock.elapsedRealtime(); + for (int i = 0; i < components; i++) { + powerComponents.get(i).init(beginTime, ITERATION_INTERVAL); + powerComponents.get(i).start(); + } + IterationData[] dataTemp = new IterationData[components]; + + PhoneConstants phoneConstants = PhoneSelector.getConstants(context); + long[] memInfo = new long[4]; + + int oledId = -1; + for (int i = 0; i < components; i++) { + if ("OLED".equals(powerComponents.get(i).getComponentName())) { + oledId = i; + break; + } + } + + double lastCurrent = -1; + + /* Indefinitely collect data on each of the power components. */ + boolean firstLogIteration = true; + for (long iter = -1; !Thread.interrupted();) { + long curTime = SystemClock.elapsedRealtime(); + /* + * Compute the next iteration that we can make the ending of. We + * wait for the end of the iteration so that the components had a + * chance to collect data already. + */ + iter = (long) Math.max(iter + 1, (curTime - beginTime) + / ITERATION_INTERVAL); + /* Sleep until the next iteration completes. */ + try { + Thread.currentThread().sleep( + beginTime + (iter + 1) * ITERATION_INTERVAL - curTime); + } catch (InterruptedException e) { + Log.e(TAG, e.toString()); + break; + } + + int totalPower = 0; + for (int i = 0; i < components; i++) { + PowerComponent comp = powerComponents.get(i); + IterationData data = comp.getData(iter); + dataTemp[i] = data; + if (data == null) { + /* + * No data present for this timestamp. No power charged. + */ + continue; + } + + SparseArray uidPower = data.getUidPowerData(); + for (int j = 0; j < uidPower.size(); j++) { + int uid = uidPower.keyAt(j); + PowerData powerData = uidPower.valueAt(j); + int power = (int) powerFunctions.get(i) + .calculate(powerData); + powerData.setCachedPower(power); + histories.get(i).add(uid, iter, power); + // histories.get(i).getTotal(uid, ) + if (uid == SystemInfo.AID_ALL) { + totalPower += power; + } + if (i == oledId) { + OLED.OledData oledData = (OLED.OledData) powerData; + if (oledData.pixPower >= 0) { + oledScoreHistory.add(uid, iter, + (int) (1000 * oledData.pixPower)); + } + } + } + } + + /* Update the uid set. */ + synchronized (fileWriteLock) { + synchronized (uidAppIds) { + for (int i = 0; i < components; i++) { + IterationData data = dataTemp[i]; + if (data == null) { + continue; + } + SparseArray uidPower = data + .getUidPowerData(); + for (int j = 0; j < uidPower.size(); j++) { + int uid = uidPower.keyAt(j); + if (uid < SystemInfo.AID_APP) { + uidAppIds.put(uid, null); + } else { + /* + * We only want to update app names when logging + * so the associcate message gets written. + */ + String appId = uidAppIds.get(uid); + String newAppId = sysInfo.getAppId(uid, pm); + if (!firstLogIteration + && logStream != null + && (appId == null || !appId + .equals(newAppId))) { + try { + logStream.write("associate " + uid + + " " + newAppId + "\n"); + } catch (IOException e) { + Log.w(TAG, + "Failed to write to log file"); + } + } + uidAppIds.put(uid, newAppId); + } + } + } + } + } + + synchronized (iterationLock) { + lastWrittenIteration = iter; + } + + /* Update the icon display every 15 iterations. */ + if (iter % 15 == 14) { + final double POLY_WEIGHT = 0.02; + int count = 0; + int[] history = getComponentHistory(5 * 60, -1, + SystemInfo.AID_ALL, -1); + double weightedAvgPower = 0; + for (int i = history.length - 1; i >= 0; i--) { + if (history[i] != 0) { + count++; + weightedAvgPower *= 1.0 - POLY_WEIGHT; + weightedAvgPower += POLY_WEIGHT * history[i] / 1000.0; + } + } + double avgPower = -1; + if (count != 0) { + avgPower = weightedAvgPower + / (1.0 - Math.pow(1.0 - POLY_WEIGHT, count)); + } + avgPower *= 1000; + + context.updateNotification( + (int) Math.min(8, + 1 + 8 * avgPower / phoneConstants.maxPower()), + avgPower); + } + + /* Update the widget. */ + if (iter % 60 == 0) { + PowerWidget.updateWidget(context, this); + } + + if (bst.hasCurrent()) { + double current = bst.getCurrent(); + if (current != lastCurrent) { + writeToLog("batt_current " + current + "\n"); + lastCurrent = current; + } + } + if (iter % (5 * 60) == 0) { + if (bst.hasTemp()) { + writeToLog("batt_temp " + bst.getTemp() + "\n"); + } + if (bst.hasCharge()) { + writeToLog("batt_charge " + bst.getCharge() + "\n"); + } + } + if (iter % (30 * 60) == 0) { + if (Settings.System.getInt(context.getContentResolver(), + "screen_brightness_mode", 0) != 0) { + writeToLog("setting_brightness automatic\n"); + } else { + int brightness = Settings.System.getInt( + context.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS, -1); + if (brightness != -1) { + writeToLog("setting_brightness " + brightness + "\n"); + } + } + int timeout = Settings.System.getInt( + context.getContentResolver(), + Settings.System.SCREEN_OFF_TIMEOUT, -1); + if (timeout != -1) { + writeToLog("setting_screen_timeout " + timeout + "\n"); + } + String httpProxy = Settings.Secure.getString( + context.getContentResolver(), + Settings.Secure.HTTP_PROXY); + if (httpProxy != null) { + writeToLog("setting_httpproxy " + httpProxy + "\n"); + } + } + + /* + * Let's only grab memory information every 10 seconds to try to + * keep log file size down and the notice_data table size down. + */ + boolean hasMem = false; + if (iter % 10 == 0) { + hasMem = sysInfo.getMemInfo(memInfo); + } + + synchronized (fileWriteLock) { + if (logStream != null) + try { + logStream.write("time " + System.currentTimeMillis() + + "\n"); + if (firstLogIteration) { + firstLogIteration = false; + Calendar cal = new GregorianCalendar(); + logStream.write("localtime_offset " + + (cal.get(Calendar.ZONE_OFFSET) + cal + .get(Calendar.DST_OFFSET)) + "\n"); + logStream.write("model " + + phoneConstants.modelName() + "\n"); + if (NotificationService.available()) { + logStream.write("notifications-active\n"); + } + if (bst.hasFullCapacity()) { + logStream.write("batt_full_capacity " + + bst.getFullCapacity() + "\n"); + } + synchronized (uidAppIds) { + for (int uid : uidAppIds.keySet()) { + if (uid < SystemInfo.AID_APP) { + continue; + } + logStream.write("associate " + uid + " " + + uidAppIds.get(uid) + "\n"); + } + } + } + logStream.write("begin " + iter + "\n"); + logStream.write("total-power " + + (long) Math.round(totalPower) + '\n'); + if (hasMem) { + logStream.write("meminfo " + memInfo[0] + " " + + memInfo[1] + " " + memInfo[2] + " " + + memInfo[3] + "\n"); + } + + /* + * Mask: lcd: 14 cpu: 13 wifi:11 3g: 7 + * + * wifi&3g: 3 cpu&wifi&3g: 1 lcd&cpu&wifi&3g: 0 + */ + + logStream.write(getConsumtionOfApps(14, sysInfo, pm)); + logStream.write(getConsumtionOfApps(13, sysInfo, pm)); + logStream.write(getConsumtionOfApps(11, sysInfo, pm)); + logStream.write(getConsumtionOfApps(7, sysInfo, pm)); + + + for (int i = 0; i < components; i++) { + IterationData data = dataTemp[i]; + if (data != null) { + String name = powerComponents.get(i) + .getComponentName(); + + SparseArray uidData = data + .getUidPowerData(); + + for (int j = 0; j < uidData.size(); j++) { + int uid = uidData.keyAt(j); + PowerData powerData = uidData.valueAt(j); + + if (uid == SystemInfo.AID_ALL) { + logStream.write(name + + " " + + (long) Math.round(powerData + .getCachedPower()) + + "\n"); + powerData.writeLogDataInfo(logStream); + } else { + String content = ""; + if (powerComponents.get(i) instanceof CPU) { + content = name + + "-" + + uid + + " " + + sysInfo + .getUidName(uid, pm) + .toString() + .replace(" ", "-") + + " " + + (long) Math + .round(powerData + .getCachedPower()) + + "\n"; + } else { + content = name + + "-" + + uid + + " " + + (long) Math + .round(powerData + .getCachedPower()) + + "\n"; + } + logStream.write(content); + + } + } + + data.recycle(); + } + } + } catch (IOException e) { + Log.w(TAG, "Failed to write to log file"); + } + + if (iter % 15 == 0 && prefs.getBoolean("sendPermission", true)) { + /* + * Allow for LogUploader to decide if the log needs to be + * uploaded and begin uploading if it decides it's + * necessary. + */ + if (logUploader.shouldUpload()) { + try { + Log.i(TAG, "close logStream now"); + logStream.close(); + } catch (IOException e) { + Log.w(TAG, "Failed to flush and close log stream"); + } + + logStream = null; + logUploader.upload(context.getFileStreamPath( + "PowerTrace.log").getAbsolutePath()); + openLog(false); + firstLogIteration = true; + } + } + } + } + + /* Blank the widget's display and turn off power button. */ + PowerWidget.updateWidgetDone(context); + + /* Have all of the power component threads exit. */ + logUploader.interrupt(); + for (int i = 0; i < components; i++) { + powerComponents.get(i).interrupt(); + } + try { + logUploader.join(); + } catch (InterruptedException e) { + Log.e(TAG, e.toString()); + } + for (int i = 0; i < components; i++) { + try { + powerComponents.get(i).join(); + } catch (InterruptedException e) { + Log.e(TAG, e.toString()); + } + } + + /* + * Close the logstream so that everything gets flushed and written to + * file before we have to quit. + */ + synchronized (fileWriteLock) { + if (logStream != null) + try { + Log.i(TAG, "close logStream now"); + logStream.close(); + } catch (IOException e) { + Log.w(TAG, "Failed to flush log file on exit"); + } + } + } + + /* + * Mask: lcd: 14 cpu: 13 wifi:11 3g: 7 + * + * wifi&3g: 3 cpu&wifi&3g: 1 lcd&cpu&wifi&3g: 0 + */ + + private String getConsumtionOfApps(int mask, SystemInfo sysInfo, + PackageManager pm) { + String content = ""; + String description = ""; + switch (mask) { + case 14: { + description = "LCD-TOTAL"; + break; + } + case 13: { + description = "CPU-TOTAL"; + break; + } + case 11: { + description = "WIFI-TOTAL"; + break; + } + case 7: { + description = "3G-TOTAL"; + break; + } + case 3: { + description = "WIFI3G"; + break; + } + case 1: { + description = "CPUWIFI3G"; + break; + } + case 0: { + description = "TOTAL"; + break; + } + default: { + description = "CONS "; + break; + } + } + + UidInfo[] uidInfos = getUidInfo( + prefs.getInt("topWindowType", Counter.WINDOW_TOTAL), mask); + + for (UidInfo uidInfo : uidInfos) { + content += description + "-" + uidInfo.uid + "-" + + sysInfo.getUidName(uidInfo.uid, pm) + " " + + uidInfo.totalEnergy + "\n"; + } + + return content; + } + + public void plug(boolean plugged) { + logUploader.plug(plugged); + } + + public void writeToLog(String m) { + synchronized (fileWriteLock) { + if (logStream != null) + try { + logStream.write(m); + } catch (IOException e) { + Log.w(TAG, + "Failed to write message to power log.. " + + e.toString()); + } + } + } + + public String[] getComponents() { + int components = powerComponents.size(); + String[] ret = new String[components]; + for (int i = 0; i < components; i++) { + ret[i] = powerComponents.get(i).getComponentName(); + } + return ret; + } + + public int[] getComponentsMaxPower() { + PhoneConstants constants = PhoneSelector.getConstants(context); + int components = powerComponents.size(); + int[] ret = new int[components]; + for (int i = 0; i < components; i++) { + ret[i] = (int) constants.getMaxPower(powerComponents.get(i) + .getComponentName()); + } + return ret; + } + + public int getNoUidMask() { + int components = powerComponents.size(); + int ret = 0; + for (int i = 0; i < components; i++) { + if (!powerComponents.get(i).hasUidInformation()) { + ret |= 1 << i; + } + } + return ret; + } + + public int[] getComponentHistory(int count, int componentId, int uid, + long iteration) { + if (iteration == -1) + synchronized (iterationLock) { + iteration = lastWrittenIteration; + } + int components = powerComponents.size(); + if (componentId == ALL_COMPONENTS) { + int[] result = new int[count]; + for (int i = 0; i < components; i++) { + int[] comp = histories.get(i).get(uid, iteration, count); + for (int j = 0; j < count; j++) { + result[j] += comp[j]; + } + } + return result; + } + if (componentId < 0 || components <= componentId) + return null; + return histories.get(componentId).get(uid, iteration, count); + } + + public long[] getTotals(int uid, int windowType) { + int components = powerComponents.size(); + long[] ret = new long[components]; + for (int i = 0; i < components; i++) { + ret[i] = histories.get(i).getTotal(uid, windowType) + * ITERATION_INTERVAL / 1000; + } + return ret; + } + + public long getRuntime(int uid, int windowType) { + long runningTime = 0; + int components = powerComponents.size(); + for (int i = 0; i < components; i++) { + long entries = histories.get(i).getCount(uid, windowType); + runningTime = entries > runningTime ? entries : runningTime; + } + return runningTime * ITERATION_INTERVAL / 1000; + } + + public long[] getMeans(int uid, int windowType) { + long[] ret = getTotals(uid, windowType); + long runningTime = getRuntime(uid, windowType); + runningTime = runningTime == 0 ? 1 : runningTime; + for (int i = 0; i < ret.length; i++) { + ret[i] /= runningTime; + } + return ret; + } + + public UidInfo[] getUidInfo(int windowType, int ignoreMask) { + long iteration; + synchronized (iterationLock) { + iteration = lastWrittenIteration; + } + int components = powerComponents.size(); + synchronized (uidAppIds) { + int pos = 0; + UidInfo[] result = new UidInfo[uidAppIds.size()]; + for (Integer uid : uidAppIds.keySet()) { + UidInfo info = UidInfo.obtain(); + int currentPower = 0; + for (int i = 0; i < components; i++) { + if ((ignoreMask & 1 << i) == 0) { + currentPower += histories.get(i).get(uid, iteration, 1)[0]; + } + } + double scale = ITERATION_INTERVAL / 1000.0; + info.init(uid, currentPower, + sumArray(getTotals(uid, windowType), ignoreMask) + * ITERATION_INTERVAL / 1000, + getRuntime(uid, windowType) * ITERATION_INTERVAL / 1000); + result[pos++] = info; + } + return result; + } + } + + private long sumArray(long[] A, int ignoreMask) { + long ret = 0; + for (int i = 0; i < A.length; i++) { + if ((ignoreMask & 1 << i) == 0) { + ret += A[i]; + } + } + return ret; + } + + public long getUidExtra(String name, int uid) { + if ("OLEDSCORE".equals(name)) { + long entries = oledScoreHistory.getCount(uid, Counter.WINDOW_TOTAL); + if (entries <= 0) + return -2; + double result = oledScoreHistory + .getTotal(uid, Counter.WINDOW_TOTAL) / 1000.0; + result /= entries; + PhoneConstants phoneConstants = PhoneSelector.getConstants(context); + result *= 255 / (phoneConstants.getMaxPower("OLED") - phoneConstants + .oledBasePower()); + return (long) Math.round(result * 100); + } + return -1; + } +} diff --git a/src/edu/umich/PowerTutor/service/UMLoggerService.java b/src/com/henny/PowerTutor2/service/UMLoggerService.java similarity index 93% rename from src/edu/umich/PowerTutor/service/UMLoggerService.java rename to src/com/henny/PowerTutor2/service/UMLoggerService.java index 0c144df..46bc9d3 100644 --- a/src/edu/umich/PowerTutor/service/UMLoggerService.java +++ b/src/com/henny/PowerTutor2/service/UMLoggerService.java @@ -17,14 +17,10 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.service; - -import edu.umich.PowerTutor.R; -import edu.umich.PowerTutor.ui.PowerTabs; -import edu.umich.PowerTutor.ui.UMLogger; -import edu.umich.PowerTutor.util.BatteryStats; -import edu.umich.PowerTutor.util.SystemInfo; +package com.henny.PowerTutor2.service; +import com.henny.PowerTutor2.R; +import com.henny.PowerTutor2.service.ICounterService; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -33,7 +29,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.os.BatteryManager; import android.os.Bundle; import android.os.IBinder; import android.telephony.PhoneStateListener; @@ -44,15 +39,20 @@ import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.io.IOException; - import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; + +import com.henny.PowerTutor2.ui.UMLogger; +import com.henny.PowerTutor2.util.BatteryStats; +import com.henny.PowerTutor2.util.SystemInfo; + public class UMLoggerService extends Service{ private static final String TAG = "UMLoggerService"; private static final int NOTIFICATION_ID = 1; private static final int NOTIFICATION_ID_LETTER = 2; + private static final int FOREGROUND_ID =2378; private Thread estimatorThread; private PowerEstimator powerEstimator; @@ -69,6 +69,7 @@ public IBinder onBind(Intent intent) { @Override public void onCreate() { + Log.i(TAG,"onCreate Service"); powerEstimator = new PowerEstimator(this); /* Register to receive phone state messages. */ @@ -134,7 +135,7 @@ public void onDestroy() { } catch(NoSuchMethodException e) { } if(!foregroundSet) { - setForeground(false); + stopForeground(false); notificationManager.cancel(NOTIFICATION_ID); } @@ -146,10 +147,10 @@ public void showNotification(){ int icon = R.drawable.level; // icon from resources - CharSequence tickerText = "PowerTutor"; // ticker-text + CharSequence tickerText = "PowerTutor2"; // ticker-text long when = System.currentTimeMillis(); // notification time Context context = getApplicationContext(); // application Context - CharSequence contentTitle = "PowerTutor"; // expanded message title + CharSequence contentTitle = "PowerTutor2"; // expanded message title CharSequence contentText = ""; // expanded message text Intent notificationIntent = new Intent(this, UMLogger.class); @@ -185,7 +186,8 @@ public void showNotification(){ } catch(NoSuchMethodException e) { } if(!foregroundSet) { - setForeground(true); + //setForeground(true); + startForeground(FOREGROUND_ID, notification); notificationManager.notify(NOTIFICATION_ID, notification); } } diff --git a/src/edu/umich/PowerTutor/service/UidInfo.java b/src/com/henny/PowerTutor2/service/UidInfo.java similarity index 95% rename from src/edu/umich/PowerTutor/service/UidInfo.java rename to src/com/henny/PowerTutor2/service/UidInfo.java index f794f9f..26dde53 100644 --- a/src/edu/umich/PowerTutor/service/UidInfo.java +++ b/src/com/henny/PowerTutor2/service/UidInfo.java @@ -17,12 +17,12 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.service; - -import edu.umich.PowerTutor.util.Recycler; +package com.henny.PowerTutor2.service; import java.io.Serializable; +import com.henny.PowerTutor2.util.Recycler; + public class UidInfo implements Serializable, Comparable { private static Recycler recycler = new Recycler(); diff --git a/src/edu/umich/PowerTutor/ui/EditPreferences.java b/src/com/henny/PowerTutor2/ui/EditPreferences.java similarity index 93% rename from src/edu/umich/PowerTutor/ui/EditPreferences.java rename to src/com/henny/PowerTutor2/ui/EditPreferences.java index 354a60e..2b2c8bb 100644 --- a/src/edu/umich/PowerTutor/ui/EditPreferences.java +++ b/src/com/henny/PowerTutor2/ui/EditPreferences.java @@ -17,10 +17,9 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.ui; - -import edu.umich.PowerTutor.R; +package com.henny.PowerTutor2.ui; +import com.henny.PowerTutor2.R; import android.os.Bundle; import android.preference.PreferenceActivity; diff --git a/src/edu/umich/PowerTutor/ui/Help.java b/src/com/henny/PowerTutor2/ui/Help.java similarity index 88% rename from src/edu/umich/PowerTutor/ui/Help.java rename to src/com/henny/PowerTutor2/ui/Help.java index 67f29c4..3431189 100644 --- a/src/edu/umich/PowerTutor/ui/Help.java +++ b/src/com/henny/PowerTutor2/ui/Help.java @@ -17,10 +17,9 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.ui; - -import edu.umich.PowerTutor.R; +package com.henny.PowerTutor2.ui; +import com.henny.PowerTutor2.R; import android.app.Activity; import android.content.Intent; import android.net.Uri; @@ -30,7 +29,7 @@ /**This function implements the UI for help view*/ public class Help extends Activity { - private static final String powerTutorUrl = "http://powertutor.org"; + private static final String powerTutorUrl = ""; @Override public void onCreate(Bundle savedInstanceState) { diff --git a/src/edu/umich/PowerTutor/ui/MiscView.java b/src/com/henny/PowerTutor2/ui/MiscView.java similarity index 94% rename from src/edu/umich/PowerTutor/ui/MiscView.java rename to src/com/henny/PowerTutor2/ui/MiscView.java index 3b8e484..e401c66 100644 --- a/src/edu/umich/PowerTutor/ui/MiscView.java +++ b/src/com/henny/PowerTutor2/ui/MiscView.java @@ -17,17 +17,10 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.ui; - -import edu.umich.PowerTutor.R; -import edu.umich.PowerTutor.phone.PhoneSelector; -import edu.umich.PowerTutor.service.ICounterService; -import edu.umich.PowerTutor.service.PowerEstimator; -import edu.umich.PowerTutor.service.UMLoggerService; -import edu.umich.PowerTutor.util.Counter; -import edu.umich.PowerTutor.util.BatteryStats; -import edu.umich.PowerTutor.util.SystemInfo; +package com.henny.PowerTutor2.ui; +import com.henny.PowerTutor2.R; +import com.henny.PowerTutor2.service.ICounterService; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; @@ -63,6 +56,13 @@ import java.util.ArrayList; import java.io.File; +import com.henny.PowerTutor2.phone.PhoneSelector; +import com.henny.PowerTutor2.service.PowerEstimator; +import com.henny.PowerTutor2.service.UMLoggerService; +import com.henny.PowerTutor2.util.BatteryStats; +import com.henny.PowerTutor2.util.Counter; +import com.henny.PowerTutor2.util.SystemInfo; + public class MiscView extends Activity { private static final String TAG = "MiscView"; diff --git a/src/edu/umich/PowerTutor/ui/PowerPie.java b/src/com/henny/PowerTutor2/ui/PowerPie.java similarity index 93% rename from src/edu/umich/PowerTutor/ui/PowerPie.java rename to src/com/henny/PowerTutor2/ui/PowerPie.java index 9600059..e408cc4 100644 --- a/src/edu/umich/PowerTutor/ui/PowerPie.java +++ b/src/com/henny/PowerTutor2/ui/PowerPie.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.ui; +package com.henny.PowerTutor2.ui; import org.achartengine.GraphicalView; import org.achartengine.chart.PieChart; @@ -25,6 +25,11 @@ import org.achartengine.renderer.DefaultRenderer; import org.achartengine.renderer.SimpleSeriesRenderer; +import com.henny.PowerTutor2.service.PowerEstimator; +import com.henny.PowerTutor2.service.UMLoggerService; +import com.henny.PowerTutor2.util.Counter; +import com.henny.PowerTutor2.util.SystemInfo; + import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; @@ -45,11 +50,7 @@ import android.view.MenuItem; import android.widget.LinearLayout; import android.widget.TextView; -import edu.umich.PowerTutor.service.ICounterService; -import edu.umich.PowerTutor.service.PowerEstimator; -import edu.umich.PowerTutor.service.UMLoggerService; -import edu.umich.PowerTutor.util.Counter; -import edu.umich.PowerTutor.util.SystemInfo; +import com.henny.PowerTutor2.service.ICounterService; public class PowerPie extends Activity { private static final String TAG = "PowerPie"; diff --git a/src/edu/umich/PowerTutor/ui/PowerTabs.java b/src/com/henny/PowerTutor2/ui/PowerTabs.java similarity index 91% rename from src/edu/umich/PowerTutor/ui/PowerTabs.java rename to src/com/henny/PowerTutor2/ui/PowerTabs.java index 5929193..ea0de86 100644 --- a/src/edu/umich/PowerTutor/ui/PowerTabs.java +++ b/src/com/henny/PowerTutor2/ui/PowerTabs.java @@ -17,17 +17,22 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.ui; +package com.henny.PowerTutor2.ui; -import edu.umich.PowerTutor.R; +import com.google.android.gms.ads.AdSize; +import com.google.android.gms.ads.AdView; +import com.henny.PowerTutor2.R; import android.app.TabActivity; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; +import android.widget.LinearLayout; import android.widget.TabHost; public class PowerTabs extends TabActivity { + + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.power_tabs); @@ -35,7 +40,7 @@ public void onCreate(Bundle savedInstanceState) { Resources res = getResources(); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; - + // TODO: We could put in some icons on each of these two tabs. Not sure if // we care enough or if it would look much better. Intent intent = new Intent(this, PowerViewer.class); diff --git a/src/com/henny/PowerTutor2/ui/PowerTop.java b/src/com/henny/PowerTutor2/ui/PowerTop.java new file mode 100644 index 0000000..23dc61e --- /dev/null +++ b/src/com/henny/PowerTutor2/ui/PowerTop.java @@ -0,0 +1,468 @@ +/* +Copyright (C) 2011 The University of Michigan + +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 . + +Please send inquiries to powertutor@umich.edu + */ + +package com.henny.PowerTutor2.ui; + +import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.AdSize; +import com.google.android.gms.ads.AdView; +import com.henny.PowerTutor2.service.ICounterService; +import com.henny.PowerTutor2.R; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.Gravity; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +import java.io.ByteArrayInputStream; +import java.io.ObjectInputStream; +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.Arrays; + +import com.henny.PowerTutor2.service.PowerEstimator; +import com.henny.PowerTutor2.service.UMLoggerService; +import com.henny.PowerTutor2.service.UidInfo; +import com.henny.PowerTutor2.util.Counter; +import com.henny.PowerTutor2.util.Recycler; +import com.henny.PowerTutor2.util.SystemInfo; + +public class PowerTop extends Activity implements Runnable { + private static final String TAG = "PowerTop"; + private static final double HIDE_UID_THRESHOLD = 0.1; + + public static final int KEY_CURRENT_POWER = 0; + public static final int KEY_AVERAGE_POWER = 1; + public static final int KEY_TOTAL_ENERGY = 2; + private static final CharSequence[] KEY_NAMES = { "Current power", + "Average power", "Energy usage" }; + + private final boolean pro=false; + + private SharedPreferences prefs; + private int noUidMask; + private String[] componentNames; + + private Intent serviceIntent; + private CounterServiceConnection conn; + private ICounterService counterService; + private Handler handler; + + private LinearLayout topGroup; + private LinearLayout filterGroup; + private LinearLayout mainView; + + private static final String ADD_ID = "ca-app-pub-4556215106095060/2018208639"; + private AdView adView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + prefs = PreferenceManager.getDefaultSharedPreferences(this); + serviceIntent = new Intent(this, UMLoggerService.class); + conn = new CounterServiceConnection(); + if (savedInstanceState != null) { + componentNames = savedInstanceState + .getStringArray("componentNames"); + noUidMask = savedInstanceState.getInt("noUidMask"); + } + + // AdView + adView = new AdView(this); + + + topGroup = new LinearLayout(this); + topGroup.setOrientation(LinearLayout.VERTICAL); + + mainView = new LinearLayout(this); + mainView.setOrientation(LinearLayout.VERTICAL); + ScrollView scrollView = new ScrollView(this); + scrollView.addView(topGroup); + filterGroup = new LinearLayout(this); + filterGroup.setOrientation(LinearLayout.HORIZONTAL); + filterGroup.setMinimumHeight(50); + + if(!pro){ + adView.setAdUnitId(ADD_ID); + adView.setAdSize(AdSize.BANNER); + // Initiate a generic request. + AdRequest adRequest = new AdRequest.Builder().build(); + // Load the adView with the ad request. + adView.loadAd(adRequest); + mainView.addView(adView); + } + + mainView.addView(filterGroup); + mainView.addView(scrollView); + } + + @Override + protected void onResume() { + super.onResume(); + handler = new Handler(); + handler.postDelayed(this, 100); + getApplicationContext().bindService(serviceIntent, conn, 0); + + refreshView(); + } + + @Override + protected void onPause() { + super.onPause(); + getApplicationContext().unbindService(conn); + handler.removeCallbacks(this); + handler = null; + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putStringArray("componentNames", componentNames); + outState.putInt("noUidMask", noUidMask); + } + + private static final int MENU_KEY = 0; + private static final int MENU_WINDOW = 1; + private static final int DIALOG_KEY = 0; + private static final int DIALOG_WINDOW = 1; + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(0, MENU_KEY, 0, "Display Type"); + menu.add(0, MENU_WINDOW, 0, "Time Span"); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + /* + * We need to make sure that the user can't cause any of the dialogs to + * be created before we have contacted the Power Tutor service to get + * the component names and such. + */ + for (int i = 0; i < menu.size(); i++) { + menu.getItem(i).setEnabled(counterService != null); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_KEY: + showDialog(DIALOG_KEY); + return true; + case MENU_WINDOW: + showDialog(DIALOG_WINDOW); + return true; + } + return false; + } + + @Override + protected Dialog onCreateDialog(int id) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + switch (id) { + case DIALOG_KEY: + builder.setTitle("Select sort key"); + builder.setItems(KEY_NAMES, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + prefs.edit().putInt("topKeyId", item).commit(); + } + }); + return builder.create(); + case DIALOG_WINDOW: + builder.setTitle("Select window type"); + builder.setItems(Counter.WINDOW_NAMES, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + prefs.edit().putInt("topWindowType", item).commit(); + } + }); + return builder.create(); + } + return null; + } + + private void refreshView() { + if (counterService == null) { + TextView loadingText = new TextView(this); + loadingText.setText("Waiting for profiler service..."); + loadingText.setGravity(Gravity.CENTER); + setContentView(loadingText); + return; + } + + int keyId = prefs.getInt("topKeyId", KEY_TOTAL_ENERGY); + try { + byte[] rawUidInfo = counterService.getUidInfo( + prefs.getInt("topWindowType", Counter.WINDOW_TOTAL), + noUidMask | prefs.getInt("topIgnoreMask", 0)); + //Log.i(TAG,"topIgnMask: "+prefs.getInt("topIgnoreMask", 0)); + if (rawUidInfo != null) { + UidInfo[] uidInfos = (UidInfo[]) new ObjectInputStream( + new ByteArrayInputStream(rawUidInfo)).readObject(); + double total = 0; + for (UidInfo uidInfo : uidInfos) { + if (uidInfo.uid == SystemInfo.AID_ALL) + continue; + switch (keyId) { + case KEY_CURRENT_POWER: + uidInfo.key = uidInfo.currentPower; + uidInfo.unit = "W"; + break; + case KEY_AVERAGE_POWER: + uidInfo.key = uidInfo.totalEnergy + / (uidInfo.runtime == 0 ? 1 : uidInfo.runtime); + uidInfo.unit = "W"; + break; + case KEY_TOTAL_ENERGY: + uidInfo.key = uidInfo.totalEnergy; + uidInfo.unit = "J"; + break; + default: + uidInfo.key = uidInfo.currentPower; + uidInfo.unit = "W"; + } + total += uidInfo.key; + } + if (total == 0) + total = 1; + for (UidInfo uidInfo : uidInfos) { + uidInfo.percentage = 100.0 * uidInfo.key / total; + } + Arrays.sort(uidInfos); + + int sz = 0; + for (int i = 0; i < uidInfos.length; i++) { + if (uidInfos[i].uid == SystemInfo.AID_ALL + || uidInfos[i].percentage < HIDE_UID_THRESHOLD) { + continue; + } + UidPowerView powerView; + if (sz < topGroup.getChildCount()) { + powerView = (UidPowerView) topGroup.getChildAt(sz); + } else { + powerView = UidPowerView.obtain(this, getIntent()); + topGroup.addView(powerView); + } + powerView.setBackgroundDrawable(null); + powerView.setBackgroundColor((sz & 1) == 0 ? 0xFF000000 + : 0xFF222222); + powerView.init(uidInfos[i], keyId); + sz++; + } + for (int i = sz; i < topGroup.getChildCount(); i++) { + UidPowerView powerView = (UidPowerView) topGroup + .getChildAt(i); + powerView.recycle(); + } + topGroup.removeViews(sz, topGroup.getChildCount() - sz); + } + } catch (IOException e) { + } catch (RemoteException e) { + } catch (ClassNotFoundException e) { + } catch (ClassCastException e) { + } + setContentView(mainView); + if (keyId == KEY_CURRENT_POWER) { + setTitle(KEY_NAMES[keyId]); + } else { + setTitle(KEY_NAMES[keyId] + + " over " + + Counter.WINDOW_DESCS[prefs.getInt("topWindowType", + Counter.WINDOW_TOTAL)]); + } + } + + public void run() { + refreshView(); + if (handler != null) { + handler.postDelayed(this, 2 * PowerEstimator.ITERATION_INTERVAL); + } + } + + private static class UidPowerView extends LinearLayout { + private static Recycler recycler = new Recycler(); + private static DecimalFormat formatter = new DecimalFormat("0.0"); + + public static UidPowerView obtain(Activity activity, Intent startIntent) { + UidPowerView result = recycler.obtain(); + if (result == null) + return new UidPowerView(activity, startIntent); + return result; + } + + public void recycle() { + recycler.recycle(this); + } + + private UidInfo uidInfo; + private String name; + private Drawable icon; + + private ImageView imageView; + private TextView textView; + + private UidPowerView(final Activity activity, final Intent startIntent) { + super(activity); + setMinimumHeight(50); + setOrientation(LinearLayout.HORIZONTAL); + imageView = new ImageView(activity); + imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + imageView.setAdjustViewBounds(true); + imageView.setMaxHeight(40); + imageView.setMaxWidth(40); + imageView.setMinimumWidth(50); + imageView.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.FILL_PARENT)); + textView = new TextView(activity); + textView.setGravity(Gravity.CENTER_VERTICAL); + textView.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.FILL_PARENT)); + addView(imageView); + addView(textView); + setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + Intent viewIntent = new Intent(v.getContext(), + PowerTabs.class); + viewIntent.putExtras(startIntent); + viewIntent.putExtra("uid", uidInfo.uid); + activity.startActivityForResult(viewIntent, 0); + } + }); + setFocusable(true); + } + + public void init(UidInfo uidInfo, int keyType) { + SystemInfo sysInfo = SystemInfo.getInstance(); + this.uidInfo = uidInfo; + PackageManager pm = getContext().getPackageManager(); + name = sysInfo.getUidName(uidInfo.uid, pm); + icon = sysInfo.getUidIcon(uidInfo.uid, pm); + imageView.setImageDrawable(icon); + String prefix; + if (uidInfo.key > 1e12) { + prefix = "G"; + uidInfo.key /= 1e12; + } else if (uidInfo.key > 1e9) { + prefix = "M"; + uidInfo.key /= 1e9; + } else if (uidInfo.key > 1e6) { + prefix = "k"; + uidInfo.key /= 1e6; + } else if (uidInfo.key > 1e3) { + prefix = ""; + uidInfo.key /= 1e3; + } else { + prefix = "m"; + } + long secs = (long) Math.round(uidInfo.runtime); + + textView.setText(String.format( + "%1$.1f%% [%3$d:%4$02d:%5$02d] %2$s\n" + "%6$.1f %7$s%8$s", + uidInfo.percentage, name, secs / 60 / 60, (secs / 60) % 60, + secs % 60, uidInfo.key, prefix, uidInfo.unit)); + } + } + + private class CounterServiceConnection implements ServiceConnection { + public void onServiceConnected(ComponentName className, + IBinder boundService) { + counterService = ICounterService.Stub + .asInterface((IBinder) boundService); + try { + componentNames = counterService.getComponents(); + noUidMask = counterService.getNoUidMask(); + filterGroup.removeAllViews(); + for (int i = 0; i < componentNames.length; i++) { + int ignMask = prefs.getInt("topIgnoreMask", 0); + if ((noUidMask & 1 << i) != 0) + continue; + final TextView filterToggle = new TextView(PowerTop.this); + final int index = i; + filterToggle.setText(componentNames[i]); + filterToggle.setGravity(Gravity.CENTER); + filterToggle + .setTextColor((ignMask & 1 << index) == 0 ? 0xFFFFFFFF + : 0xFF888888); + filterToggle + .setBackgroundColor(filterGroup.getChildCount() % 2 == 0 ? 0xFF444444 + : 0xFF555555); + filterToggle.setFocusable(true); + filterToggle.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + int ignMask = prefs.getInt("topIgnoreMask", 0); + if ((ignMask & 1 << index) == 0) { + prefs.edit() + .putInt("topIgnoreMask", + ignMask | 1 << index).commit(); + filterToggle.setTextColor(0xFF888888); + } else { + prefs.edit() + .putInt("topIgnoreMask", + ignMask & ~(1 << index)) + .commit(); + filterToggle.setTextColor(0xFFFFFFFF); + } + } + }); + filterGroup.addView(filterToggle, + new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.FILL_PARENT, 1f)); + } + } catch (RemoteException e) { + counterService = null; + } + } + + public void onServiceDisconnected(ComponentName className) { + counterService = null; + getApplicationContext().unbindService(conn); + getApplicationContext().bindService(serviceIntent, conn, 0); + Log.w(TAG, "Unexpectedly lost connection to service"); + } + } +} diff --git a/src/com/henny/PowerTutor2/ui/PowerViewer.java b/src/com/henny/PowerTutor2/ui/PowerViewer.java new file mode 100644 index 0000000..22bb228 --- /dev/null +++ b/src/com/henny/PowerTutor2/ui/PowerViewer.java @@ -0,0 +1,369 @@ +/* +Copyright (C) 2011 The University of Michigan + +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 . + +Please send inquiries to powertutor@umich.edu + */ + +package com.henny.PowerTutor2.ui; + +import org.achartengine.GraphicalView; +import org.achartengine.chart.CubicLineChart; +import org.achartengine.model.XYMultipleSeriesDataset; +import org.achartengine.model.XYSeries; +import org.achartengine.renderer.XYMultipleSeriesRenderer; +import org.achartengine.renderer.XYSeriesRenderer; + +import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.AdSize; +import com.google.android.gms.ads.AdView; +import com.henny.PowerTutor2.service.ICounterService; +import com.henny.PowerTutor2.service.PowerEstimator; +import com.henny.PowerTutor2.service.UMLoggerService; +import com.henny.PowerTutor2.util.SystemInfo; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.SystemClock; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.Gravity; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +public class PowerViewer extends Activity { + private static final String TAG = "PowerViewer"; + + private SharedPreferences prefs; + private int uid; + + private int components; + private String[] componentNames; + private int[] componentsMaxPower; + private int noUidMask; + private boolean collecting; + + private ValueCollector[] collectors; + + private Intent serviceIntent; + private CounterServiceConnection conn; + private ICounterService counterService; + + private Handler handler; + private LinearLayout chartLayout; + + public void refreshView() { + if (counterService == null) { + TextView loadingText = new TextView(this); + loadingText.setText("Waiting for profiler service..."); + loadingText.setGravity(Gravity.CENTER); + setContentView(loadingText); + return; + } + chartLayout = new LinearLayout(this); + chartLayout.setOrientation(LinearLayout.VERTICAL); + + if (uid == SystemInfo.AID_ALL) { + /* + * If we are reporting global power usage then just set noUidMask to + * 0 so that all components get displayed. + */ + noUidMask = 0; + } + components = 0; + for (int i = 0; i < componentNames.length; i++) { + if ((noUidMask & 1 << i) == 0) { + components++; + } + } + boolean showTotal = prefs.getBoolean("showTotalPower", false); + collectors = new ValueCollector[(showTotal ? 1 : 0) + components]; + + int pos = 0; + for (int i = showTotal ? -1 : 0; i < componentNames.length; i++) { + if (i != -1 && (noUidMask & 1 << i) != 0) { + continue; + } + String name = i == -1 ? "Total" : componentNames[i]; + double mxPower = (i == -1 ? 2100.0 : componentsMaxPower[i]) * 1.05; + + XYSeries series = new XYSeries(name); + XYMultipleSeriesDataset mseries = new XYMultipleSeriesDataset(); + mseries.addSeries(series); + + XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer(); + XYSeriesRenderer srenderer = new XYSeriesRenderer(); + renderer.setYAxisMin(0.0); + renderer.setYAxisMax(mxPower); + renderer.setYTitle(name + "(mW)"); + + int clr = PowerPie.COLORS[(PowerPie.COLORS.length + i) + % PowerPie.COLORS.length]; + srenderer.setColor(clr); + srenderer.setFillBelowLine(true); + srenderer.setFillBelowLineColor(((clr >> 1) & 0x7F7F7F) + | (clr & 0xFF000000)); + renderer.addSeriesRenderer(srenderer); + + View chartView = new GraphicalView(this, new CubicLineChart( + mseries, renderer, 0.5f)); + chartView.setMinimumHeight(100); + chartLayout.addView(chartView); + + collectors[pos] = new ValueCollector(series, renderer, chartView, i); + if (handler != null) { + handler.post(collectors[pos]); + } + pos++; + } + + /* + * We're giving 100 pixels per graph of vertical space for the chart + * view. If we don't specify a minimum height the chart view ends up + * having a height of 0 so this is important. + */ + chartLayout.setMinimumHeight(100 * components); + + ScrollView scrollView = new ScrollView(this) { + public boolean onInterceptTouchEvent(android.view.MotionEvent ev) { + return true; + } + }; + + scrollView.addView(chartLayout); + scrollView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); + setContentView(scrollView); + } + + private class CounterServiceConnection implements ServiceConnection { + public void onServiceConnected(ComponentName className, + IBinder boundService) { + counterService = ICounterService.Stub + .asInterface((IBinder) boundService); + try { + componentNames = counterService.getComponents(); + componentsMaxPower = counterService.getComponentsMaxPower(); + noUidMask = counterService.getNoUidMask(); + refreshView(); + } catch (RemoteException e) { + counterService = null; + } + } + + public void onServiceDisconnected(ComponentName className) { + counterService = null; + getApplicationContext().unbindService(conn); + getApplicationContext().bindService(serviceIntent, conn, 0); + Log.w(TAG, "Unexpectedly lost connection to service"); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + prefs = PreferenceManager.getDefaultSharedPreferences(this); + uid = getIntent().getIntExtra("uid", SystemInfo.AID_ALL); + + collecting = true; + if (savedInstanceState != null) { + collecting = savedInstanceState.getBoolean("collecting", true); + componentNames = savedInstanceState + .getStringArray("componentNames"); + noUidMask = savedInstanceState.getInt("noUidMask"); + } + + serviceIntent = new Intent(this, UMLoggerService.class); + conn = new CounterServiceConnection(); + } + + @Override + protected void onResume() { + super.onResume(); + handler = new Handler(); + getApplicationContext().bindService(serviceIntent, conn, 0); + + refreshView(); + } + + @Override + protected void onPause() { + super.onPause(); + getApplicationContext().unbindService(conn); + if (collectors != null) + for (int i = 0; i < components; i++) { + handler.removeCallbacks(collectors[i]); + } + counterService = null; + handler = null; + collecting = true; + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean("collecting", collecting); + outState.putStringArray("componentNames", componentNames); + outState.putInt("noUidMask", noUidMask); + } + + /* Let all of the UI graphs lay themselves out again. */ + private void stateChanged() { + for (int i = 0; i < components; i++) { + collectors[i].layout(); + } + } + + private static final int MENU_OPTIONS = 0; + private static final int MENU_TOGGLE_COLLECTING = 1; + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(0, MENU_OPTIONS, 0, "Options"); + menu.add(0, MENU_TOGGLE_COLLECTING, 0, ""); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + menu.findItem(MENU_TOGGLE_COLLECTING).setTitle( + collecting ? "Pause" : "Resume"); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_OPTIONS: + startActivity(new Intent(this, ViewerPreferences.class)); + return true; + case MENU_TOGGLE_COLLECTING: + collecting = !collecting; + if (handler != null) { + if (collecting) + for (int i = 0; i < components; i++) { + collectors[i].reset(); + handler.post(collectors[i]); + } + else + for (int i = 0; i < components; i++) { + handler.removeCallbacks(collectors[i]); + } + } + break; + } + return false; + } + + public class ValueCollector implements Runnable { + private XYSeries series; + private XYMultipleSeriesRenderer renderer; + private View chartView; + + private int componentId; + private long lastTime; + + int[] values; + + private boolean readHistory; + + public ValueCollector(XYSeries series, + XYMultipleSeriesRenderer renderer, View chartView, + int componentId) { + this.series = series; + this.renderer = renderer; + this.chartView = chartView; + this.componentId = componentId; + lastTime = SystemClock.elapsedRealtime(); + layout(); + } + + public void layout() { + int numVals = Integer.parseInt(prefs.getString("viewNumValues_s", + "60")); + values = new int[numVals]; + + renderer.clearXTextLabels(); + renderer.setXAxisMin(0); + renderer.setXAxisMax(numVals - 1); + renderer.addXTextLabel(numVals - 1, "" + numVals); + renderer.setXLabels(0); + for (int j = 0; j < 10; j++) { + renderer.addXTextLabel(numVals * j / 10, "" + + (1 + numVals * j / 10)); + } + + reset(); + } + + /** Restart points collecting from zero. */ + public void reset() { + series.clear(); + readHistory = true; + } + + public void run() { + int numVals = Integer.parseInt(prefs.getString("viewNumValues_s", + "60")); + if (counterService != null) + try { + if (readHistory) { + values = counterService.getComponentHistory(numVals, + componentId, uid); + readHistory = false; + } else { + for (int i = numVals - 1; i > 0; i--) { + values[i] = values[i - 1]; + } + values[0] = counterService.getComponentHistory(1, + componentId, uid)[0]; + } + } catch (RemoteException e) { + Log.w(TAG, "Failed to get data from service"); + for (int i = 0; i < numVals; i++) { + values[i] = 0; + } + } + + series.clear(); + for (int i = 0; i < numVals; i++) { + series.add(i, values[i]); + } + + long curTime = SystemClock.elapsedRealtime(); + long tryTime = lastTime + + PowerEstimator.ITERATION_INTERVAL + * (long) Math.max(1, 1 + (curTime - lastTime) + / PowerEstimator.ITERATION_INTERVAL); + if (handler != null) { + handler.postDelayed(this, tryTime - curTime); + } + + chartView.invalidate(); + } + }; +} diff --git a/src/edu/umich/PowerTutor/ui/StartupReceiver.java b/src/com/henny/PowerTutor2/ui/StartupReceiver.java similarity index 93% rename from src/edu/umich/PowerTutor/ui/StartupReceiver.java rename to src/com/henny/PowerTutor2/ui/StartupReceiver.java index df3a3d2..e01211a 100644 --- a/src/edu/umich/PowerTutor/ui/StartupReceiver.java +++ b/src/com/henny/PowerTutor2/ui/StartupReceiver.java @@ -17,9 +17,9 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.ui; +package com.henny.PowerTutor2.ui; -import edu.umich.PowerTutor.service.UMLoggerService; +import com.henny.PowerTutor2.service.UMLoggerService; import android.content.BroadcastReceiver; import android.content.Context; diff --git a/src/com/henny/PowerTutor2/ui/UMLogger.java b/src/com/henny/PowerTutor2/ui/UMLogger.java new file mode 100644 index 0000000..17781ce --- /dev/null +++ b/src/com/henny/PowerTutor2/ui/UMLogger.java @@ -0,0 +1,383 @@ +/* +Copyright (C) 2011 The University of Michigan + +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 . + +Please send inquiries to powertutor@umich.edu + */ + +package com.henny.PowerTutor2.ui; + +import com.henny.PowerTutor2.service.ICounterService; +import com.henny.PowerTutor2.R; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.ComponentName; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.Environment; +import android.os.IBinder; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.Random; +import java.util.zip.InflaterInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; + +import com.henny.PowerTutor2.phone.PhoneSelector; +import com.henny.PowerTutor2.service.UMLoggerService; + +/** The main view activity for PowerTutor */ +public class UMLogger extends Activity { + private static final String TAG = "UMLogger"; + + public static final String CURRENT_VERSION = "1.2"; // Don't change this... + + public static final String SERVER_IP = ""; + public static final int SERVER_PORT = 0; + + private SharedPreferences prefs; + private Intent serviceIntent; + private ICounterService counterService; + private CounterServiceConnection conn; + + private Button serviceStartButton; + private Button appViewerButton; + private Button sysViewerButton; + private Button helpButton; + private TextView scaleText; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + + prefs = PreferenceManager.getDefaultSharedPreferences(this); + + serviceIntent = new Intent(this, UMLoggerService.class); + conn = new CounterServiceConnection(); + + setContentView(R.layout.main); + ArrayAdapter adapterxaxis = ArrayAdapter.createFromResource(this, + R.array.xaxis, android.R.layout.simple_spinner_item); + adapterxaxis + .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + + serviceStartButton = (Button) findViewById(R.id.servicestartbutton); + appViewerButton = (Button) findViewById(R.id.appviewerbutton); + sysViewerButton = (Button) findViewById(R.id.sysviewerbutton); + helpButton = (Button) findViewById(R.id.helpbutton); + + serviceStartButton.setOnClickListener(serviceStartButtonListener); + sysViewerButton.setOnClickListener(sysViewerButtonListener); + appViewerButton.setOnClickListener(appViewerButtonListener); + helpButton.setOnClickListener(helpButtonListener); + + if (counterService != null) { + serviceStartButton.setText("Stop Profiler"); + appViewerButton.setEnabled(true); + sysViewerButton.setEnabled(true); + } else { + serviceStartButton.setText("Start Profiler"); + appViewerButton.setEnabled(false); + sysViewerButton.setEnabled(false); + } + + } + + @Override + public void onResume() { + super.onResume(); + getApplicationContext().bindService(serviceIntent, conn, 0); + if (prefs.getBoolean("firstRun", true)) { + if (PhoneSelector.getPhoneType() == PhoneSelector.PHONE_UNKNOWN) { + // showDialog(DIALOG_UNKNOWN_PHONE); + } else { + showDialog(DIALOG_TOS); + } + } + Intent startingIntent = getIntent(); + if (startingIntent.getBooleanExtra("isFromIcon", false)) { + Intent copyIntent = (Intent) getIntent().clone(); + copyIntent.putExtra("isFromIcon", false); + setIntent(copyIntent); + Intent intent = new Intent(this, PowerTabs.class); + startActivity(intent); + } + } + + @Override + public void onPause() { + super.onPause(); + getApplicationContext().unbindService(conn); + } + + private static final int MENU_PREFERENCES = 0; + private static final int MENU_SAVE_LOG = 1; + private static final int DIALOG_START_SENDING = 0; + private static final int DIALOG_STOP_SENDING = 1; + private static final int DIALOG_TOS = 2; + private static final int DIALOG_RUNNING_ON_STARTUP = 3; + private static final int DIALOG_NOT_RUNNING_ON_STARTUP = 4; + private static final int DIALOG_UNKNOWN_PHONE = 5; + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(0, MENU_PREFERENCES, 0, "Options"); + menu.add(0, MENU_SAVE_LOG, 0, "Save log"); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_PREFERENCES: + startActivity(new Intent(this, EditPreferences.class)); + return true; + case MENU_SAVE_LOG: + + if (appViewerButton.isEnabled()) { + + Toast.makeText(UMLogger.this, "Stop Profiler to save log-file", + Toast.LENGTH_SHORT).show(); + + } else { + + new Thread() { + public void start() { + + File writeFile = new File(Environment + .getExternalStorageDirectory() + .getAbsolutePath(), "PowerTrace" + + System.currentTimeMillis() + ".log"); + int count = 0; + try { + + InflaterInputStream logIn = new InflaterInputStream( + openFileInput("PowerTrace.log")); + + BufferedOutputStream logOut = new BufferedOutputStream( + new FileOutputStream(writeFile)); + + byte[] buffer = new byte[20480]; + for (int ln = logIn.read(buffer); ln != -1; ln = logIn + .read(buffer)) { + logOut.write(buffer, 0, ln); + count++; + } + logIn.close(); + logOut.close(); + Toast.makeText( + UMLogger.this, + "Wrote log to " + + writeFile.getAbsolutePath(), + Toast.LENGTH_SHORT).show(); + return; + } catch (java.io.EOFException e) { + Toast.makeText( + UMLogger.this, + "Wrote log to " + + writeFile.getAbsolutePath() + " " + + count, Toast.LENGTH_SHORT).show(); + return; + } catch (IOException e) { + Toast.makeText( + UMLogger.this, + "Failed to write log to sdcard" + + e.toString(), Toast.LENGTH_SHORT) + .show(); + } + + } + }.start(); + } + return true; + } + return super.onOptionsItemSelected(item); + } + + /** This function includes all the dialog constructor */ + @Override + protected Dialog onCreateDialog(int id) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + switch (id) { + case DIALOG_TOS: + builder.setMessage(R.string.term) + .setCancelable(false) + .setPositiveButton("Agree", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int id) { + prefs.edit().putBoolean("firstRun", false) + .putBoolean("runOnStartup", true) + .putBoolean("sendPermission", true) + .commit(); + dialog.dismiss(); + } + }) + .setNegativeButton("Do not agree", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int id) { + prefs.edit().putBoolean("firstRun", true) + .commit(); + finish(); + } + }); + return builder.create(); + case DIALOG_STOP_SENDING: + builder.setMessage(R.string.stop_sending_text) + .setCancelable(true) + .setPositiveButton("Stop", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int id) { + prefs.edit() + .putBoolean("sendPermission", false) + .commit(); + dialog.dismiss(); + } + }) + .setNegativeButton("Cancel", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int id) { + dialog.cancel(); + } + }); + return builder.create(); + case DIALOG_START_SENDING: + builder.setMessage(R.string.start_sending_text) + .setCancelable(true) + .setPositiveButton("Start", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int id) { + prefs.edit() + .putBoolean("sendPermission", true) + .commit(); + dialog.dismiss(); + } + }) + .setNegativeButton("Cancel", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int id) { + dialog.cancel(); + } + }); + return builder.create(); + case DIALOG_RUNNING_ON_STARTUP: + builder.setMessage(R.string.running_on_startup).setCancelable(true) + .setNeutralButton("Ok", null); + return builder.create(); + case DIALOG_NOT_RUNNING_ON_STARTUP: + builder.setMessage(R.string.not_running_on_startup) + .setCancelable(true).setNeutralButton("Ok", null); + return builder.create(); + case DIALOG_UNKNOWN_PHONE: + builder.setMessage(R.string.unknown_phone) + .setCancelable(false) + .setNeutralButton("Ok", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int id) { + dialog.dismiss(); + showDialog(DIALOG_TOS); + } + }); + return builder.create(); + + } + return null; + } + + private Button.OnClickListener appViewerButtonListener = new Button.OnClickListener() { + public void onClick(View v) { + Intent intent = new Intent(v.getContext(), PowerTop.class); + startActivityForResult(intent, 0); + } + }; + + private Button.OnClickListener sysViewerButtonListener = new Button.OnClickListener() { + public void onClick(View v) { + Intent intent = new Intent(v.getContext(), PowerTabs.class); + startActivityForResult(intent, 0); + } + }; + + private Button.OnClickListener serviceStartButtonListener = new Button.OnClickListener() { + public void onClick(View v) { + serviceStartButton.setEnabled(false); + if (counterService != null) { + stopService(serviceIntent); + } else { + if (conn == null) { + Toast.makeText(UMLogger.this, "Profiler failed to start", + Toast.LENGTH_SHORT).show(); + } else { + startService(serviceIntent); + } + } + } + }; + + private class CounterServiceConnection implements ServiceConnection { + public void onServiceConnected(ComponentName className, + IBinder boundService) { + counterService = ICounterService.Stub + .asInterface((IBinder) boundService); + serviceStartButton.setText("Stop Profiler"); + serviceStartButton.setEnabled(true); + appViewerButton.setEnabled(true); + sysViewerButton.setEnabled(true); + } + + public void onServiceDisconnected(ComponentName className) { + counterService = null; + getApplicationContext().unbindService(conn); + getApplicationContext().bindService(serviceIntent, conn, 0); + + Toast.makeText(UMLogger.this, "Profiler stopped", + Toast.LENGTH_SHORT).show(); + serviceStartButton.setText("Start Profiler"); + serviceStartButton.setEnabled(true); + appViewerButton.setEnabled(false); + sysViewerButton.setEnabled(false); + } + } + + private Button.OnClickListener helpButtonListener = new Button.OnClickListener() { + public void onClick(View v) { + Intent myIntent = new Intent(v.getContext(), Help.class); + startActivityForResult(myIntent, 0); + } + }; +} diff --git a/src/edu/umich/PowerTutor/ui/ViewerPreferences.java b/src/com/henny/PowerTutor2/ui/ViewerPreferences.java similarity index 93% rename from src/edu/umich/PowerTutor/ui/ViewerPreferences.java rename to src/com/henny/PowerTutor2/ui/ViewerPreferences.java index 525df62..537b9ae 100644 --- a/src/edu/umich/PowerTutor/ui/ViewerPreferences.java +++ b/src/com/henny/PowerTutor2/ui/ViewerPreferences.java @@ -17,10 +17,9 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.ui; - -import edu.umich.PowerTutor.R; +package com.henny.PowerTutor2.ui; +import com.henny.PowerTutor2.R; import android.os.Bundle; import android.preference.PreferenceActivity; diff --git a/src/edu/umich/PowerTutor/util/BatteryStats.java b/src/com/henny/PowerTutor2/util/BatteryStats.java similarity index 99% rename from src/edu/umich/PowerTutor/util/BatteryStats.java rename to src/com/henny/PowerTutor2/util/BatteryStats.java index 1448b12..4b5c501 100644 --- a/src/edu/umich/PowerTutor/util/BatteryStats.java +++ b/src/com/henny/PowerTutor2/util/BatteryStats.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.util; +package com.henny.PowerTutor2.util; import java.io.File; diff --git a/src/edu/umich/PowerTutor/util/Counter.java b/src/com/henny/PowerTutor2/util/Counter.java similarity index 99% rename from src/edu/umich/PowerTutor/util/Counter.java rename to src/com/henny/PowerTutor2/util/Counter.java index 0508d93..1efd35d 100644 --- a/src/edu/umich/PowerTutor/util/Counter.java +++ b/src/com/henny/PowerTutor2/util/Counter.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.util; +package com.henny.PowerTutor2.util; import android.os.SystemClock; diff --git a/src/edu/umich/PowerTutor/util/ForegroundDetector.java b/src/com/henny/PowerTutor2/util/ForegroundDetector.java similarity index 97% rename from src/edu/umich/PowerTutor/util/ForegroundDetector.java rename to src/com/henny/PowerTutor2/util/ForegroundDetector.java index a38a3ae..10582f3 100644 --- a/src/edu/umich/PowerTutor/util/ForegroundDetector.java +++ b/src/com/henny/PowerTutor2/util/ForegroundDetector.java @@ -17,9 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.util; - -import edu.umich.PowerTutor.util.SystemInfo; +package com.henny.PowerTutor2.util; import android.app.ActivityManager; @@ -27,6 +25,8 @@ import java.util.BitSet; import java.util.List; +import com.henny.PowerTutor2.util.SystemInfo; + /* This detector looks for transitions where one app leaves the foreground and * another enters the foreground to detect apps that are legitimately in the * foreground. If no application is known to be legitimate system is returned. diff --git a/src/edu/umich/PowerTutor/util/HexEncode.java b/src/com/henny/PowerTutor2/util/HexEncode.java similarity index 97% rename from src/edu/umich/PowerTutor/util/HexEncode.java rename to src/com/henny/PowerTutor2/util/HexEncode.java index eb9d975..23937db 100644 --- a/src/edu/umich/PowerTutor/util/HexEncode.java +++ b/src/com/henny/PowerTutor2/util/HexEncode.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.util; +package com.henny.PowerTutor2.util; public class HexEncode { public static String encode(byte[] bytes) { diff --git a/src/edu/umich/PowerTutor/util/HistoryBuffer.java b/src/com/henny/PowerTutor2/util/HistoryBuffer.java similarity index 95% rename from src/edu/umich/PowerTutor/util/HistoryBuffer.java rename to src/com/henny/PowerTutor2/util/HistoryBuffer.java index 65fe0a1..f2d96bc 100644 --- a/src/edu/umich/PowerTutor/util/HistoryBuffer.java +++ b/src/com/henny/PowerTutor2/util/HistoryBuffer.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.util; +package com.henny.PowerTutor2.util; import android.util.SparseArray; diff --git a/src/edu/umich/PowerTutor/util/NativeLoader.java b/src/com/henny/PowerTutor2/util/NativeLoader.java similarity index 97% rename from src/edu/umich/PowerTutor/util/NativeLoader.java rename to src/com/henny/PowerTutor2/util/NativeLoader.java index 926f5bb..bb93184 100644 --- a/src/edu/umich/PowerTutor/util/NativeLoader.java +++ b/src/com/henny/PowerTutor2/util/NativeLoader.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.util; +package com.henny.PowerTutor2.util; import android.util.Log; diff --git a/src/edu/umich/PowerTutor/util/NotificationService.java b/src/com/henny/PowerTutor2/util/NotificationService.java similarity index 99% rename from src/edu/umich/PowerTutor/util/NotificationService.java rename to src/com/henny/PowerTutor2/util/NotificationService.java index c5539b2..6e9c513 100644 --- a/src/edu/umich/PowerTutor/util/NotificationService.java +++ b/src/com/henny/PowerTutor2/util/NotificationService.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.util; +package com.henny.PowerTutor2.util; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -29,7 +29,7 @@ import android.os.Parcel; import android.os.RemoteException; import android.util.Log; -import edu.umich.PowerTutor.PowerNotifications; +import com.henny.PowerTutor2.PowerNotifications; @SuppressWarnings("unchecked") public class NotificationService { diff --git a/src/edu/umich/PowerTutor/util/Recycler.java b/src/com/henny/PowerTutor2/util/Recycler.java similarity index 97% rename from src/edu/umich/PowerTutor/util/Recycler.java rename to src/com/henny/PowerTutor2/util/Recycler.java index 677f3db..7a9bd2c 100644 --- a/src/edu/umich/PowerTutor/util/Recycler.java +++ b/src/com/henny/PowerTutor2/util/Recycler.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.util; +package com.henny.PowerTutor2.util; import java.util.Vector; diff --git a/src/edu/umich/PowerTutor/util/SystemInfo.java b/src/com/henny/PowerTutor2/util/SystemInfo.java similarity index 99% rename from src/edu/umich/PowerTutor/util/SystemInfo.java rename to src/com/henny/PowerTutor2/util/SystemInfo.java index 9799438..17c5e96 100644 --- a/src/edu/umich/PowerTutor/util/SystemInfo.java +++ b/src/com/henny/PowerTutor2/util/SystemInfo.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.util; +package com.henny.PowerTutor2.util; import java.io.BufferedReader; import java.io.File; @@ -206,6 +206,7 @@ public int getUidForPid(int pid) { } } } + rdr.close(); } catch(IOException e) { Log.w(TAG, "Failed to manually read in process uid"); } diff --git a/src/edu/umich/PowerTutor/widget/Configure.java b/src/com/henny/PowerTutor2/widget/Configure.java similarity index 97% rename from src/edu/umich/PowerTutor/widget/Configure.java rename to src/com/henny/PowerTutor2/widget/Configure.java index cf2046a..cf34124 100644 --- a/src/edu/umich/PowerTutor/widget/Configure.java +++ b/src/com/henny/PowerTutor2/widget/Configure.java @@ -17,11 +17,9 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.widget; - -import edu.umich.PowerTutor.R; -import edu.umich.PowerTutor.util.HexEncode; +package com.henny.PowerTutor2.widget; +import com.henny.PowerTutor2.R; import android.app.Activity; import android.appwidget.AppWidgetManager; import android.content.Context; @@ -42,6 +40,8 @@ import java.io.ObjectOutputStream; import java.io.IOException; +import com.henny.PowerTutor2.util.HexEncode; + public class Configure extends Activity { private static final String TAG = "Configure"; diff --git a/src/edu/umich/PowerTutor/widget/DataSource.java b/src/com/henny/PowerTutor2/widget/DataSource.java similarity index 97% rename from src/edu/umich/PowerTutor/widget/DataSource.java rename to src/com/henny/PowerTutor2/widget/DataSource.java index 575845f..ee8534b 100644 --- a/src/edu/umich/PowerTutor/widget/DataSource.java +++ b/src/com/henny/PowerTutor2/widget/DataSource.java @@ -17,14 +17,14 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.widget; +package com.henny.PowerTutor2.widget; import java.io.Serializable; -import edu.umich.PowerTutor.service.PowerEstimator; -import edu.umich.PowerTutor.util.BatteryStats; -import edu.umich.PowerTutor.util.Counter; -import edu.umich.PowerTutor.util.SystemInfo; +import com.henny.PowerTutor2.service.PowerEstimator; +import com.henny.PowerTutor2.util.BatteryStats; +import com.henny.PowerTutor2.util.Counter; +import com.henny.PowerTutor2.util.SystemInfo; public class DataSource implements Serializable { private static final long serialVersionUID = 14594389587290845L; diff --git a/src/edu/umich/PowerTutor/widget/DataSourceConfigure.java b/src/com/henny/PowerTutor2/widget/DataSourceConfigure.java similarity index 98% rename from src/edu/umich/PowerTutor/widget/DataSourceConfigure.java rename to src/com/henny/PowerTutor2/widget/DataSourceConfigure.java index e056d4c..30960dc 100644 --- a/src/edu/umich/PowerTutor/widget/DataSourceConfigure.java +++ b/src/com/henny/PowerTutor2/widget/DataSourceConfigure.java @@ -17,10 +17,9 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.widget; - -import edu.umich.PowerTutor.R; +package com.henny.PowerTutor2.widget; +import com.henny.PowerTutor2.R; import android.app.Activity; import android.appwidget.AppWidgetManager; import android.content.Context; diff --git a/src/edu/umich/PowerTutor/widget/PowerWidget.java b/src/com/henny/PowerTutor2/widget/PowerWidget.java similarity index 93% rename from src/edu/umich/PowerTutor/widget/PowerWidget.java rename to src/com/henny/PowerTutor2/widget/PowerWidget.java index c19a042..c4090a2 100644 --- a/src/edu/umich/PowerTutor/widget/PowerWidget.java +++ b/src/com/henny/PowerTutor2/widget/PowerWidget.java @@ -17,7 +17,7 @@ Please send inquiries to powertutor@umich.edu */ -package edu.umich.PowerTutor.widget; +package com.henny.PowerTutor2.widget; import android.app.PendingIntent; import android.appwidget.AppWidgetProvider; @@ -29,19 +29,19 @@ import android.preference.PreferenceManager; import android.util.Log; import android.widget.RemoteViews; - -import edu.umich.PowerTutor.R; -import edu.umich.PowerTutor.service.PowerEstimator; -import edu.umich.PowerTutor.service.UMLoggerService; -import edu.umich.PowerTutor.ui.UMLogger; -import edu.umich.PowerTutor.util.Counter; -import edu.umich.PowerTutor.util.HexEncode; -import edu.umich.PowerTutor.util.SystemInfo; +import com.henny.PowerTutor2.R; import java.io.ByteArrayInputStream; import java.io.ObjectInputStream; import java.io.IOException; +import com.henny.PowerTutor2.service.PowerEstimator; +import com.henny.PowerTutor2.service.UMLoggerService; +import com.henny.PowerTutor2.ui.UMLogger; +import com.henny.PowerTutor2.util.Counter; +import com.henny.PowerTutor2.util.HexEncode; +import com.henny.PowerTutor2.util.SystemInfo; + public class PowerWidget extends AppWidgetProvider { private static final String TAG = "PowerWidget"; diff --git a/src/edu/umich/PowerTutor/components/CPU.java b/src/edu/umich/PowerTutor/components/CPU.java deleted file mode 100644 index 283e991..0000000 --- a/src/edu/umich/PowerTutor/components/CPU.java +++ /dev/null @@ -1,358 +0,0 @@ -/* -Copyright (C) 2011 The University of Michigan - -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 . - -Please send inquiries to powertutor@umich.edu -*/ - -package edu.umich.PowerTutor.components; - -import edu.umich.PowerTutor.phone.PhoneConstants; -import edu.umich.PowerTutor.service.IterationData; -import edu.umich.PowerTutor.service.PowerData; -import edu.umich.PowerTutor.util.Recycler; -import edu.umich.PowerTutor.util.SystemInfo; - -import android.util.Log; -import android.os.Process; -import android.os.SystemClock; -import android.util.SparseArray; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; - -public class CPU extends PowerComponent { - public static class CpuData extends PowerData { - private static Recycler recycler = new Recycler(); - - public static CpuData obtain() { - CpuData result = recycler.obtain(); - if(result != null) return result; - return new CpuData(); - } - - @Override - public void recycle() { - recycler.recycle(this); - } - - public double sysPerc; - public double usrPerc; - public double freq; - - private CpuData() { - } - - public void init(double sysPerc, double usrPerc, double freq) { - this.sysPerc = sysPerc; - this.usrPerc = usrPerc; - this.freq = freq; - } - - public void writeLogDataInfo(OutputStreamWriter out) throws IOException { - StringBuilder res = new StringBuilder(); - res.append("CPU-sys ").append((long)Math.round(sysPerc)) - .append("\nCPU-usr ").append((long)Math.round(usrPerc)) - .append("\nCPU-freq ").append(freq) - .append("\n"); - out.write(res.toString()); - } - } - - private static final String TAG = "CPU"; - private static final String CPU_FREQ_FILE = "/proc/cpuinfo"; - private static final String STAT_FILE = "/proc/stat"; - - private CpuStateKeeper cpuState; - private SparseArray pidStates; - private SparseArray uidLinks; - - private int[] pids; - private long[] statsBuf; - - private PhoneConstants constants; - - public CPU(PhoneConstants constants) { - this.constants = constants; - cpuState = new CpuStateKeeper(SystemInfo.AID_ALL); - pidStates = new SparseArray(); - uidLinks = new SparseArray(); - statsBuf = new long[7]; - } - - @Override - public IterationData calculateIteration(long iteration) { - IterationData result = IterationData.obtain(); - - SystemInfo sysInfo = SystemInfo.getInstance(); - double freq = readCpuFreq(sysInfo); - if(freq < 0) { - Log.w(TAG, "Failed to read cpu frequency"); - return result; - } - - if(!sysInfo.getUsrSysTotalTime(statsBuf)) { - Log.w(TAG, "Failed to read cpu times"); - return result; - } - - long usrTime = statsBuf[SystemInfo.INDEX_USER_TIME]; - long sysTime = statsBuf[SystemInfo.INDEX_SYS_TIME]; - long totalTime = statsBuf[SystemInfo.INDEX_TOTAL_TIME]; - - boolean init = cpuState.isInitialized(); - cpuState.updateState(usrTime, sysTime, totalTime, iteration); - - if(init) { - CpuData data = CpuData.obtain(); - data.init(cpuState.getUsrPerc(), cpuState.getSysPerc(), freq); - result.setPowerData(data); - } - - uidLinks.clear(); - pids = sysInfo.getPids(pids); - int pidInd = 0; - if(pids != null) for(int pid : pids) { - if(pid < 0) { - break; - } - - CpuStateKeeper pidState; - if(pidInd < pidStates.size() && pidStates.keyAt(pidInd) == pid) { - pidState = pidStates.valueAt(pidInd); - } else { - int uid = sysInfo.getUidForPid(pid); - if(uid >= 0) { - pidState = new CpuStateKeeper(uid); - pidStates.put(pid, pidState); - } else { - /* Assume that this process no longer exists. */ - continue; - } - } - pidInd++; - - if(!pidState.isStale(iteration)) { - /* Nothing much is going on with this pid recently. We'll just - * assume that it's not using any of the cpu for this iteration. - */ - pidState.updateIteration(iteration, totalTime); - } else if(sysInfo.getPidUsrSysTime(pid, statsBuf)) { - usrTime = statsBuf[SystemInfo.INDEX_USER_TIME]; - sysTime = statsBuf[SystemInfo.INDEX_SYS_TIME]; - - init = pidState.isInitialized(); - pidState.updateState(usrTime, sysTime, totalTime, iteration); - - if(!init) { - continue; - } - } - - CpuStateKeeper linkState = uidLinks.get(pidState.getUid()); - if(linkState == null) { - uidLinks.put(pidState.getUid(), pidState); - } else { - linkState.absorb(pidState); - } - } - - /* Remove processes that are no longer active. */ - for(int i = 0; i < pidStates.size(); i++) { - if(!pidStates.valueAt(i).isAlive(iteration)) { - pidStates.remove(pidStates.keyAt(i--)); - } - } - - /* Collect the summed uid information. */ - for(int i = 0; i < uidLinks.size(); i++) { - int uid = uidLinks.keyAt(i); - CpuStateKeeper linkState = uidLinks.valueAt(i); - - CpuData uidData = CpuData.obtain(); - predictAppUidState(uidData, linkState.getUsrPerc(), - linkState.getSysPerc(), freq); - result.addUidPowerData(uid, uidData); - } - - return result; - } - - /* This is the function that is responsible for predicting the cpu frequency - * state of the individual uid as though it were the only thing running. It - * simply is finding the lowest frequency that keeps the cpu usage under - * 70% assuming there is a linear relationship to the cpu utilization at - * different frequencies. - */ - private void predictAppUidState(CpuData uidData, double usrPerc, - double sysPerc, double freq) { - double[] freqs = constants.cpuFreqs(); - if(usrPerc + sysPerc < 1e-6) { - /* Don't waste time with the binary search if there is no utilization - * which will be the case a lot. - */ - uidData.init(sysPerc, usrPerc, freqs[0]); - return; - } - int lo = 0; - int hi = freqs.length - 1; - double perc = sysPerc + usrPerc; - while(lo < hi) { - int mid = (lo + hi) / 2; - double nperc = perc * freq / freqs[mid]; - if(nperc < 70) { - hi = mid; - } else { - lo = mid + 1; - } - } - uidData.init(sysPerc * freq / freqs[lo], usrPerc * freq / freqs[lo], - freqs[lo]); - } - - private static class CpuStateKeeper { - private int uid; - private long iteration; - private long lastUpdateIteration; - private long inactiveIterations; - - private long lastUsr; - private long lastSys; - private long lastTotal; - - private long sumUsr; - private long sumSys; - private long deltaTotal; - - private CpuStateKeeper(int uid) { - this.uid = uid; - lastUsr = lastSys = -1; - lastUpdateIteration = iteration = -1; - inactiveIterations = 0; - } - - public boolean isInitialized() { - return lastUsr != -1; - } - - public void updateIteration(long iteration, long totalTime) { - /* Process is still running but actually reading the cpu utilization has - * been skipped this iteration to avoid wasting cpu cycles as this process - * has not been very active recently. */ - sumUsr = 0; - sumSys = 0; - deltaTotal = totalTime - lastTotal; - if(deltaTotal < 1) deltaTotal = 1; - lastTotal = totalTime; - this.iteration = iteration; - } - - public void updateState(long usrTime, long sysTime, long totalTime, - long iteration) { - sumUsr = usrTime - lastUsr; - sumSys = sysTime - lastSys; - deltaTotal = totalTime - lastTotal; - if(deltaTotal < 1) deltaTotal = 1; - lastUsr = usrTime; - lastSys = sysTime; - lastTotal = totalTime; - lastUpdateIteration = this.iteration = iteration; - - if(getUsrPerc() + getSysPerc() < 0.1) { - inactiveIterations++; - } else { - inactiveIterations = 0; - } - } - - public int getUid() { - return uid; - } - - public void absorb(CpuStateKeeper s) { - sumUsr += s.sumUsr; - sumSys += s.sumSys; - } - - public double getUsrPerc() { - return 100.0 * sumUsr / Math.max(sumUsr + sumSys, deltaTotal); - } - - public double getSysPerc() { - return 100.0 * sumSys / Math.max(sumUsr + sumSys, deltaTotal); - } - - public boolean isAlive(long iteration) { - return this.iteration == iteration; - } - - public boolean isStale(long iteration) { - return 1L << (iteration - lastUpdateIteration) > - inactiveIterations * inactiveIterations; - } - } - - @Override - public boolean hasUidInformation() { - return true; - } - - @Override - public String getComponentName() { - return "CPU"; - } - - /* Returns the frequency of the processor in Mhz. If the frequency cannot - * be determined returns a negative value instead. - */ - private double readCpuFreq(SystemInfo sysInfo) { - /* Try to read from the /sys/devices file first. If that doesn't work - * try manually inspecting the /proc/cpuinfo file. - */ - long cpuFreqKhz = sysInfo.readLongFromFile( - "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"); - if(cpuFreqKhz != -1) { - return cpuFreqKhz / 1000.0; - } - - FileReader fstream; - try { - fstream = new FileReader(CPU_FREQ_FILE); - } catch (FileNotFoundException e) { - Log.w(TAG, "Could not read cpu frequency file"); - return -1; - } - BufferedReader in = new BufferedReader(fstream, 500); - String line; - try { - while((line = in.readLine()) != null) { - if(line.startsWith("BogoMIPS")) { - return Double.parseDouble(line.trim().split("[ :]+")[1]); - } - } - } catch(IOException e) { - /* Failed to read from the cpu freq file. */ - } catch(NumberFormatException e) { - /* Frequency not formatted properly as a double. */ - } - Log.w(TAG, "Failed to read cpu frequency"); - return -1; - } -} diff --git a/src/edu/umich/PowerTutor/components/Wifi.java b/src/edu/umich/PowerTutor/components/Wifi.java deleted file mode 100644 index 0e10292..0000000 --- a/src/edu/umich/PowerTutor/components/Wifi.java +++ /dev/null @@ -1,418 +0,0 @@ -/* -Copyright (C) 2011 The University of Michigan - -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 . - -Please send inquiries to powertutor@umich.edu -*/ - -package edu.umich.PowerTutor.components; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStreamWriter; - -import android.content.Context; -import android.net.wifi.WifiManager; -import android.os.SystemClock; -import android.util.Log; -import android.util.SparseArray; -import edu.umich.PowerTutor.phone.PhoneConstants; -import edu.umich.PowerTutor.service.IterationData; -import edu.umich.PowerTutor.service.PowerData; -import edu.umich.PowerTutor.util.Recycler; -import edu.umich.PowerTutor.util.SystemInfo; - -public class Wifi extends PowerComponent { - public static class WifiData extends PowerData { - private static Recycler recycler = new Recycler(); - - public static WifiData obtain() { - WifiData result = recycler.obtain(); - if(result != null) return result; - return new WifiData(); - } - - @Override - public void recycle() { - recycler.recycle(this); - } - - public boolean wifiOn; - public double packets; - public long uplinkBytes; - public long downlinkBytes; - public double uplinkRate; - public double linkSpeed; - public int powerState; - - private WifiData() { - } - - public void init(double packets, long uplinkBytes, long downlinkBytes, - double uplinkRate, double linkSpeed, int powerState) { - wifiOn = true; - this.packets = packets; - this.uplinkBytes = uplinkBytes; - this.downlinkBytes = downlinkBytes; - this.uplinkRate = uplinkRate; - this.linkSpeed = linkSpeed; - this.powerState = powerState; - } - - public void init() { - wifiOn = false; - } - - public void writeLogDataInfo(OutputStreamWriter out) throws IOException { - StringBuilder res = new StringBuilder(); - res.append("Wifi-on ").append(wifiOn).append("\n"); - if(wifiOn) { - res.append("Wifi-packets ").append((long)Math.round(packets)) - .append("\nWifi-uplinkBytes ").append(uplinkBytes) - .append("\nWifi-downlinkBytes ").append(downlinkBytes) - .append("\nWifi-uplink ").append((long)Math.round(uplinkRate)) - .append("\nWifi-speed ").append((long)Math.round(linkSpeed)) - .append("\nWifi-state ").append(Wifi.POWER_STATE_NAMES[powerState]) - .append("\n"); - } - out.write(res.toString()); - } - } - - public static final int POWER_STATE_LOW = 0; - public static final int POWER_STATE_HIGH = 1; - public static final String[] POWER_STATE_NAMES = {"LOW", "HIGH"}; - - private static final String TAG = "Wifi"; - - private PhoneConstants phoneConstants; - private WifiManager wifiManager; - private SystemInfo sysInfo; - - private long lastLinkSpeed; - private int[] lastUids; - private WifiStateKeeper wifiState; - private SparseArray uidStates; - - private String transPacketsFile; - private String readPacketsFile; - private String transBytesFile; - private String readBytesFile; - private File uidStatsFolder; - - public Wifi(Context context, PhoneConstants phoneConstants) { - this.phoneConstants = phoneConstants; - wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); - sysInfo = SystemInfo.getInstance(); - - /* Try to grab the interface name. If we can't find it will take a wild - * stab in the dark. - */ - String interfaceName = SystemInfo.getInstance().getProperty("wifi.interface"); - if(interfaceName == null) interfaceName = "eth0"; - - lastLinkSpeed = -1; - wifiState = new WifiStateKeeper(phoneConstants.wifiHighLowTransition(), - phoneConstants.wifiLowHighTransition()); - uidStates = new SparseArray(); - transPacketsFile = "/sys/devices/virtual/net/" + - interfaceName + "/statistics/tx_packets"; - readPacketsFile = "/sys/devices/virtual/net/" + - interfaceName + "/statistics/rx_packets"; - transBytesFile = "/sys/devices/virtual/net/" + - interfaceName + "/statistics/tx_bytes"; - readBytesFile = "/sys/devices/virtual/net/" + - interfaceName + "/statistics/rx_bytes"; - uidStatsFolder = new File("/proc/uid_stat"); - } - - @Override - public IterationData calculateIteration(long iteration) { - IterationData result = IterationData.obtain(); - - int wifiStateFlag = wifiManager.getWifiState(); - if(wifiStateFlag != WifiManager.WIFI_STATE_ENABLED && - wifiStateFlag != WifiManager.WIFI_STATE_DISABLING) { - /* We need to allow the real iterface state keeper to reset it's state - * so that the next update it knows it's coming back from an off state. - * We also need to clear all the uid information. - */ - wifiState.interfaceOff(); - uidStates.clear(); - lastLinkSpeed = -1; - - WifiData data = WifiData.obtain(); - data.init(); - result.setPowerData(data); - return result; - } - - long transmitPackets = sysInfo.readLongFromFile(transPacketsFile); - long receivePackets = sysInfo.readLongFromFile(readPacketsFile); - long transmitBytes = sysInfo.readLongFromFile(transBytesFile); - long receiveBytes = sysInfo.readLongFromFile(readBytesFile); - if(transmitPackets == -1 || receivePackets == -1 || - transmitBytes == -1 || receiveBytes == -1) { - /* Couldn't read interface data files. */ - Log.w(TAG, "Failed to read packet and byte counts from wifi interface"); - return result; - } - - /* Update the link speed every 15 seconds as pulling the WifiInfo structure - * from WifiManager is a little bit expensive. This isn't really something - * that is likely to change very frequently anyway. - */ - if(iteration % 15 == 0 || lastLinkSpeed == -1) { - lastLinkSpeed = wifiManager.getConnectionInfo().getLinkSpeed(); - } - double linkSpeed = lastLinkSpeed; - - if(wifiState.isInitialized()) { - wifiState.updateState(transmitPackets, receivePackets, - transmitBytes, receiveBytes); - WifiData data = WifiData.obtain(); - data.init(wifiState.getPackets(), wifiState.getUplinkBytes(), - wifiState.getDownlinkBytes(), wifiState.getUplinkRate(), - linkSpeed, wifiState.getPowerState()); - result.setPowerData(data); - } else { - wifiState.updateState(transmitPackets, receivePackets, - transmitBytes, receiveBytes); - } - - lastUids = sysInfo.getUids(lastUids); - if(lastUids != null) for(int uid : lastUids) { - if(uid == -1) { - continue; - } - try { - WifiStateKeeper uidState = uidStates.get(uid); - if(uidState == null) { - uidState = new WifiStateKeeper(phoneConstants.wifiHighLowTransition(), - phoneConstants.wifiLowHighTransition()); - uidStates.put(uid, uidState); - } - - if(!uidState.isStale()) { - /* We use a huerstic here so that we don't poll for uids that haven't - * had much activity recently. - */ - continue; - } - - /* These read operations are the expensive part of polling. */ - receiveBytes = sysInfo.readLongFromFile( - "/proc/uid_stat/" + uid + "/tcp_rcv"); - transmitBytes = sysInfo.readLongFromFile( - "/proc/uid_stat/" + uid + "/tcp_snd"); - - if(receiveBytes == -1 || transmitBytes == -1) { - Log.w(TAG, "Failed to read uid read/write byte counts"); - } else if(uidState.isInitialized()) { - /* We only have information about bytes received but what we really - * want is the number of packets received so we just have to - * estimate it. - */ - long deltaTransmitBytes = transmitBytes - uidState.getTransmitBytes(); - long deltaReceiveBytes = receiveBytes - uidState.getReceiveBytes(); - long estimatedTransmitPackets = (long)Math.round(deltaTransmitBytes / - wifiState.getAverageTransmitPacketSize()); - long estimatedReceivePackets = (long)Math.round(deltaReceiveBytes / - wifiState.getAverageReceivePacketSize()); - if(deltaTransmitBytes > 0 && estimatedTransmitPackets == 0) { - estimatedTransmitPackets = 1; - } - if(deltaReceiveBytes > 0 && estimatedReceivePackets == 0) { - estimatedReceivePackets = 1; - } - - boolean active = transmitBytes != uidState.getTransmitBytes() || - receiveBytes != uidState.getReceiveBytes(); - uidState.updateState( - uidState.getTransmitPackets() + estimatedTransmitPackets, - uidState.getReceivePackets() + estimatedReceivePackets, - transmitBytes, receiveBytes); - - if(active) { - WifiData uidData = WifiData.obtain(); - uidData.init(uidState.getPackets(), uidState.getUplinkBytes(), - uidState.getDownlinkBytes(), uidState.getUplinkRate(), - linkSpeed, uidState.getPowerState()); - result.addUidPowerData(uid, uidData); - } - } else { - uidState.updateState(0, 0, transmitBytes, receiveBytes); - } - } catch(NumberFormatException e) { - Log.w(TAG, "Non-uid files in /proc/uid_stat"); - } - } - - return result; - } - - private static class WifiStateKeeper { - private long lastTransmitPackets; - private long lastReceivePackets; - private long lastTransmitBytes; - private long lastReceiveBytes; - private long lastTime; - - private int powerState; - private double lastPackets; - private double lastUplinkRate; - private double lastAverageTransmitPacketSize; - private double lastAverageReceivePacketSize; - - private long deltaUplinkBytes; - private long deltaDownlinkBytes; - - private double highLowTransition; - private double lowHighTransition; - - private long inactiveTime; - - public WifiStateKeeper(double highLowTransition, double lowHighTransition) { - this.highLowTransition = highLowTransition; - this.lowHighTransition = lowHighTransition; - lastTransmitPackets = lastReceivePackets = lastTransmitBytes = - lastTime = -1; - powerState = POWER_STATE_LOW; - lastPackets = lastUplinkRate = 0; - lastAverageTransmitPacketSize = 1000; - lastAverageReceivePacketSize = 1000; - inactiveTime = 0; - } - - public void interfaceOff() { - lastTime = SystemClock.elapsedRealtime(); - powerState = POWER_STATE_LOW; - } - - public boolean isInitialized() { - return lastTime != -1; - } - - public void updateState(long transmitPackets, long receivePackets, - long transmitBytes, long receiveBytes) { - long curTime = SystemClock.elapsedRealtime(); - if(lastTime != -1 && curTime > lastTime) { - double deltaTime = curTime - lastTime; - lastUplinkRate = (transmitBytes - lastTransmitBytes) / 1024.0 * - 7.8125 / deltaTime; - lastPackets = receivePackets + transmitPackets - - lastReceivePackets - lastTransmitPackets; - deltaUplinkBytes = transmitBytes - lastTransmitBytes; - deltaDownlinkBytes = receiveBytes - lastReceiveBytes; - if(transmitPackets != lastTransmitPackets) { - lastAverageTransmitPacketSize = 0.9 * lastAverageTransmitPacketSize + - 0.1 * (transmitBytes - lastTransmitBytes) / - (transmitPackets - lastTransmitPackets); - } - if(receivePackets != lastReceivePackets) { - lastAverageReceivePacketSize = 0.9 * lastAverageReceivePacketSize + - 0.1 * (receiveBytes - lastReceiveBytes) / - (receivePackets - lastReceivePackets); - } - - if(receiveBytes != lastReceiveBytes || - transmitBytes != lastTransmitBytes) { - inactiveTime = 0; - } else { - inactiveTime += curTime - lastTime; - } - - if(lastPackets < highLowTransition) { - powerState = POWER_STATE_LOW; - } else if(lastPackets > lowHighTransition) { - powerState = POWER_STATE_HIGH; - } - } - lastTime = curTime; - lastTransmitPackets = transmitPackets; - lastReceivePackets = receivePackets; - lastTransmitBytes = transmitBytes; - lastReceiveBytes = receiveBytes; - } - - public int getPowerState() { - return powerState; - } - - public double getPackets() { - return lastPackets; - } - - public long getUplinkBytes() { - return deltaUplinkBytes; - } - - public long getDownlinkBytes() { - return deltaDownlinkBytes; - } - - public double getUplinkRate() { - return lastUplinkRate; - } - - public double getAverageTransmitPacketSize() { - return lastAverageTransmitPacketSize; - } - - public double getAverageReceivePacketSize() { - return lastAverageReceivePacketSize; - } - - public long getTransmitPackets() { - return lastTransmitPackets; - } - - public long getReceivePackets() { - return lastReceivePackets; - } - - public long getTransmitBytes() { - return lastTransmitBytes; - } - - public long getReceiveBytes() { - return lastReceiveBytes; - } - - /* The idea here is that we don't want to have to read uid information - * every single iteration for each uid as it just takes too long. So here - * we are designing a hueristic that helps us avoid polling for too many - * uids. - */ - public boolean isStale() { - long curTime = SystemClock.elapsedRealtime(); - return curTime - lastTime > (long)Math.min(10000, inactiveTime); - } - } - - private long readLongFromFile(String filePath) { - return sysInfo.readLongFromFile(filePath); - } - - @Override - public boolean hasUidInformation() { - return uidStatsFolder.exists(); - } - - @Override - public String getComponentName() { - return "Wifi"; - } -} diff --git a/src/edu/umich/PowerTutor/phone/PhoneSelector.java b/src/edu/umich/PowerTutor/phone/PhoneSelector.java deleted file mode 100644 index 54ebd43..0000000 --- a/src/edu/umich/PowerTutor/phone/PhoneSelector.java +++ /dev/null @@ -1,204 +0,0 @@ -/* -Copyright (C) 2011 The University of Michigan - -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 . - -Please send inquiries to powertutor@umich.edu -*/ - -package edu.umich.PowerTutor.phone; - -import java.util.List; - -import android.content.Context; -import android.os.Build; -import android.util.Log; -import edu.umich.PowerTutor.components.Audio; -import edu.umich.PowerTutor.components.CPU; -import edu.umich.PowerTutor.components.GPS; -import edu.umich.PowerTutor.components.LCD; -import edu.umich.PowerTutor.components.OLED; -import edu.umich.PowerTutor.components.PowerComponent; -import edu.umich.PowerTutor.components.Sensors; -import edu.umich.PowerTutor.components.Threeg; -import edu.umich.PowerTutor.components.Wifi; -import edu.umich.PowerTutor.components.Audio.AudioData; -import edu.umich.PowerTutor.components.CPU.CpuData; -import edu.umich.PowerTutor.components.GPS.GpsData; -import edu.umich.PowerTutor.components.LCD.LcdData; -import edu.umich.PowerTutor.components.OLED.OledData; -import edu.umich.PowerTutor.components.Sensors.SensorData; -import edu.umich.PowerTutor.components.Threeg.ThreegData; -import edu.umich.PowerTutor.components.Wifi.WifiData; -import edu.umich.PowerTutor.service.PowerData; -import edu.umich.PowerTutor.util.NotificationService; -import edu.umich.PowerTutor.util.SystemInfo; - -public class PhoneSelector { - private static final String TAG = "PhoneSelector"; - - public static final int PHONE_UNKNOWN = 0; - public static final int PHONE_DREAM = 1; /* G1 */ - public static final int PHONE_SAPPHIRE = 2; /* G2 */ - public static final int PHONE_PASSION = 3; /* Nexus One */ - - /* A hard-coded list of phones that have OLED screens. */ - public static final String[] OLED_PHONES = { - "bravo", - "passion", - "GT-I9000", - "inc", - "legend", - "GT-I7500", - "SPH-M900", - "SGH-I897", - "SGH-T959", - "desirec", - }; - - - /* This class is not supposed to be instantiated. Just use the static - * members. - */ - private PhoneSelector() {} - - public static boolean phoneSupported() { - return getPhoneType() != PHONE_UNKNOWN; - } - - public static boolean hasOled() { - for(int i = 0; i < OLED_PHONES.length; i++) { - if(Build.DEVICE.equals(OLED_PHONES[i])) { - return true; - } - } - return false; - } - - public static int getPhoneType() { - if(Build.DEVICE.startsWith("dream")) return PHONE_DREAM; - if(Build.DEVICE.startsWith("sapphire")) return PHONE_SAPPHIRE; - if(Build.DEVICE.startsWith("passion")) return PHONE_PASSION; - return PHONE_UNKNOWN; - } - - public static PhoneConstants getConstants(Context context) { - switch(getPhoneType()) { - case PHONE_DREAM: - return new DreamConstants(context); - case PHONE_SAPPHIRE: - return new SapphireConstants(context); - case PHONE_PASSION: - return new PassionConstants(context); - default: - boolean oled = hasOled(); - Log.w(TAG, "Phone type not recognized (" + Build.DEVICE + "), using " + - (oled ? "Passion" : "Dream") + " constants"); - return oled ? new PassionConstants(context) : - new DreamConstants(context); - } - } - - public static PhonePowerCalculator getCalculator(Context context) { - switch(getPhoneType()) { - case PHONE_DREAM: - return new DreamPowerCalculator(context); - case PHONE_SAPPHIRE: - return new SapphirePowerCalculator(context); - case PHONE_PASSION: - return new PassionPowerCalculator(context); - default: - boolean oled = hasOled(); - Log.w(TAG, "Phone type not recognized (" + Build.DEVICE + "), using " + - (oled ? "Passion" : "Dream") + " calculator"); - return oled ? new PassionPowerCalculator(context) : - new DreamPowerCalculator(context); - } - } - - public static void generateComponents(Context context, - List components, - List functions) { - final PhoneConstants constants = getConstants(context); - final PhonePowerCalculator calculator = getCalculator(context); - - //TODO: What about bluetooth? - //TODO: LED light on the Nexus - - /* Add display component. */ - if(hasOled()) { - components.add(new OLED(context, constants)); - functions.add(new PowerFunction() { - public double calculate(PowerData data) { - return calculator.getOledPower((OledData)data); - }}); - } else { - components.add(new LCD(context)); - functions.add(new PowerFunction() { - public double calculate(PowerData data) { - return calculator.getLcdPower((LcdData)data); - }}); - } - - /* Add CPU component. */ - components.add(new CPU(constants)); - functions.add(new PowerFunction() { - public double calculate(PowerData data) { - return calculator.getCpuPower((CpuData)data); - }}); - - /* Add Wifi component. */ - String wifiInterface = - SystemInfo.getInstance().getProperty("wifi.interface"); - if(wifiInterface != null && wifiInterface.length() != 0) { - components.add(new Wifi(context, constants)); - functions.add(new PowerFunction() { - public double calculate(PowerData data) { - return calculator.getWifiPower((WifiData)data); - }}); - } - - /* Add 3G component. */ - if(constants.threegInterface().length() != 0) { - components.add(new Threeg(context, constants)); - functions.add(new PowerFunction() { - public double calculate(PowerData data) { - return calculator.getThreeGPower((ThreegData)data); - }}); - } - - /* Add GPS component. */ - components.add(new GPS(context, constants)); - functions.add(new PowerFunction() { - public double calculate(PowerData data) { - return calculator.getGpsPower((GpsData)data); - }}); - - /* Add Audio component. */ - components.add(new Audio(context)); - functions.add(new PowerFunction() { - public double calculate(PowerData data) { - return calculator.getAudioPower((AudioData)data); - }}); - - /* Add Sensors component if avaialble. */ - if(NotificationService.available()) { - components.add(new Sensors(context)); - functions.add(new PowerFunction() { - public double calculate(PowerData data) { - return calculator.getSensorPower((SensorData)data); - }}); - } - } -} diff --git a/src/edu/umich/PowerTutor/service/PowerEstimator.java b/src/edu/umich/PowerTutor/service/PowerEstimator.java deleted file mode 100644 index ed0325a..0000000 --- a/src/edu/umich/PowerTutor/service/PowerEstimator.java +++ /dev/null @@ -1,586 +0,0 @@ -/* -Copyright (C) 2011 The University of Michigan - -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 . - -Please send inquiries to powertutor@umich.edu -*/ - -package edu.umich.PowerTutor.service; - -import edu.umich.PowerTutor.components.PowerComponent; -import edu.umich.PowerTutor.components.OLED; -import edu.umich.PowerTutor.phone.PhoneSelector; -import edu.umich.PowerTutor.phone.PhoneConstants; -import edu.umich.PowerTutor.phone.PowerFunction; -import edu.umich.PowerTutor.util.BatteryStats; -import edu.umich.PowerTutor.util.Counter; -import edu.umich.PowerTutor.util.HistoryBuffer; -import edu.umich.PowerTutor.util.NotificationService; -import edu.umich.PowerTutor.util.SystemInfo; -import edu.umich.PowerTutor.widget.PowerWidget; - -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.os.SystemClock; -import android.preference.PreferenceManager; -import android.provider.Settings; -import android.util.Log; -import android.util.SparseArray; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.text.DecimalFormat; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Map; -import java.util.Vector; -import java.util.zip.Deflater; -import java.util.zip.DeflaterOutputStream; - -/** This class is responsible for starting the individual power component - * loggers (CPU, GPS, etc...) and collecting the information they generate. - * This information is used both to write a log file that will be send back - * to spidermoneky (or looked at by the user) and to implement the - * ICounterService IPC interface. - */ -public class PowerEstimator implements Runnable { - private static final String TAG = "PowerEstimator"; - - /* A dictionary used to assist in compression of the log files. Strings that - * appear more frequently should be put towards the end of the dictionary. It - * is not critical that every string that be written to the log appear here. - */ - private static final String DEFLATE_DICTIONARY = - "onoffidleoff-hookringinglowairplane-modebatteryedgeGPRS3Gunknown" + - "in-serviceemergency-onlyout-of-servicepower-offdisconnectedconnecting" + - "associateconnectedsuspendedphone-callservicenetworkbegin.0123456789" + - "GPSAudioWifi3GLCDCPU-power "; - - public static final int ALL_COMPONENTS = -1; - public static final int ITERATION_INTERVAL = 1000; // 1 second - - private UMLoggerService context; - private SharedPreferences prefs; - private boolean plugged; - - private Vector powerComponents; - private Vector powerFunctions; - private Vector histories; - private Map uidAppIds; - - // Miscellaneous data. - private HistoryBuffer oledScoreHistory; - - private Object fileWriteLock = new Object(); - private LogUploader logUploader; - private OutputStreamWriter logStream; - private DeflaterOutputStream deflateStream; - - private Object iterationLock = new Object(); - private long lastWrittenIteration; - - public PowerEstimator(UMLoggerService context){ - this.context = context; - prefs = PreferenceManager.getDefaultSharedPreferences(context); - powerComponents = new Vector(); - powerFunctions = new Vector(); - uidAppIds = new HashMap(); - PhoneSelector.generateComponents(context, powerComponents, powerFunctions); - - histories = new Vector(); - for(int i = 0; i < powerComponents.size(); i++) { - histories.add(new HistoryBuffer(300)); - } - oledScoreHistory = new HistoryBuffer(0); - - logUploader = new LogUploader(context); - openLog(true); - } - - private void openLog(boolean init) { - /* Open up the log file if possible. */ - try { - String logFilename = context.getFileStreamPath( - "PowerTrace.log").getAbsolutePath(); - if(init && prefs.getBoolean("sendPermission", true) && - new File(logFilename).length() > 0) { - /* There is data to send. Make sure that gets going in the sending - * process before we write over any old logs. - */ - logUploader.upload(logFilename); - } - Deflater deflater = new Deflater(); - deflater.setDictionary(DEFLATE_DICTIONARY.getBytes()); - deflateStream = new DeflaterOutputStream( - new FileOutputStream(logFilename)); - logStream = new OutputStreamWriter(deflateStream); - } catch(IOException e) { - logStream = null; - Log.e(TAG, "Failed to open log file. No log will be kept."); - } - } - - /** This is the loop that keeps updating the power profile - */ - public void run() { - SystemInfo sysInfo = SystemInfo.getInstance(); - PackageManager pm = context.getPackageManager(); - BatteryStats bst = BatteryStats.getInstance(); - - int components = powerComponents.size(); - long beginTime = SystemClock.elapsedRealtime(); - for(int i = 0; i < components; i++) { - powerComponents.get(i).init(beginTime, ITERATION_INTERVAL); - powerComponents.get(i).start(); - } - IterationData[] dataTemp = new IterationData[components]; - - PhoneConstants phoneConstants = PhoneSelector.getConstants(context); - long[] memInfo = new long[4]; - - int oledId = -1; - for(int i = 0; i < components; i++) { - if("OLED".equals(powerComponents.get(i).getComponentName())) { - oledId = i; - break; - } - } - - double lastCurrent = -1; - - /* Indefinitely collect data on each of the power components. */ - boolean firstLogIteration = true; - for(long iter = -1; !Thread.interrupted(); ) { - long curTime = SystemClock.elapsedRealtime(); - /* Compute the next iteration that we can make the ending of. We wait - for the end of the iteration so that the components had a chance to - collect data already. - */ - iter = (long)Math.max(iter + 1, - (curTime - beginTime) / ITERATION_INTERVAL); - /* Sleep until the next iteration completes. */ - try { - Thread.currentThread().sleep( - beginTime + (iter + 1) * ITERATION_INTERVAL - curTime); - } catch(InterruptedException e) { - break; - } - - int totalPower = 0; - for(int i = 0; i < components; i++) { - PowerComponent comp = powerComponents.get(i); - IterationData data = comp.getData(iter); - dataTemp[i] = data; - if(data == null) { - /* No data present for this timestamp. No power charged. - */ - continue; - } - - SparseArray uidPower = data.getUidPowerData(); - for(int j = 0; j < uidPower.size(); j++) { - int uid = uidPower.keyAt(j); - PowerData powerData = uidPower.valueAt(j); - int power = (int)powerFunctions.get(i).calculate(powerData); - powerData.setCachedPower(power); - histories.get(i).add(uid, iter, power); - if(uid == SystemInfo.AID_ALL) { - totalPower += power; - } - if(i == oledId) { - OLED.OledData oledData = (OLED.OledData)powerData; - if(oledData.pixPower >= 0) { - oledScoreHistory.add(uid, iter, (int)(1000 * oledData.pixPower)); - } - } - } - } - - /* Update the uid set. */ - synchronized(fileWriteLock) { synchronized(uidAppIds) { - for(int i = 0; i < components; i++) { - IterationData data = dataTemp[i]; - if(data == null) { - continue; - } - SparseArray uidPower = data.getUidPowerData(); - for(int j = 0; j < uidPower.size(); j++) { - int uid = uidPower.keyAt(j); - if(uid < SystemInfo.AID_APP) { - uidAppIds.put(uid, null); - } else { - /* We only want to update app names when logging so the associcate - * message gets written. - */ - String appId = uidAppIds.get(uid); - String newAppId = sysInfo.getAppId(uid, pm); - if(!firstLogIteration && logStream != null && - (appId == null || !appId.equals(newAppId))) { - try { - logStream.write("associate " + uid + " " + newAppId + "\n"); - } catch(IOException e) { - Log.w(TAG, "Failed to write to log file"); - } - } - uidAppIds.put(uid, newAppId); - } - } - } - }} - - synchronized(iterationLock) { - lastWrittenIteration = iter; - } - - /* Update the icon display every 15 iterations. */ - if(iter % 15 == 14) { - final double POLY_WEIGHT = 0.02; - int count = 0; - int[] history = getComponentHistory(5 * 60, -1, - SystemInfo.AID_ALL, -1); - double weightedAvgPower = 0; - for(int i = history.length - 1; i >= 0; i--) { - if(history[i] != 0) { - count++; - weightedAvgPower *= 1.0 - POLY_WEIGHT; - weightedAvgPower += POLY_WEIGHT * history[i] / 1000.0; - } - } - double avgPower = -1; - if(count != 0) { - avgPower = weightedAvgPower / - (1.0 - Math.pow(1.0 - POLY_WEIGHT, count)); - } - avgPower *= 1000; - - context.updateNotification((int)Math.min(8, 1 + - 8 * avgPower / phoneConstants.maxPower()), - avgPower); - } - - /* Update the widget. */ - if(iter % 60 == 0) { - PowerWidget.updateWidget(context, this); - } - - if(bst.hasCurrent()) { - double current = bst.getCurrent(); - if(current != lastCurrent) { - writeToLog("batt_current " + current + "\n"); - lastCurrent = current; - } - } - if(iter % (5*60) == 0) { - if(bst.hasTemp()) { - writeToLog("batt_temp " + bst.getTemp() + "\n"); - } - if(bst.hasCharge()) { - writeToLog("batt_charge " + bst.getCharge() + "\n"); - } - } - if(iter % (30*60) == 0) { - if(Settings.System.getInt(context.getContentResolver(), - "screen_brightness_mode", 0) != 0) { - writeToLog("setting_brightness automatic\n"); - } else { - int brightness = Settings.System.getInt( - context.getContentResolver(), - Settings.System.SCREEN_BRIGHTNESS, -1); - if(brightness != -1) { - writeToLog("setting_brightness " + brightness + "\n"); - } - } - int timeout = Settings.System.getInt( - context.getContentResolver(), - Settings.System.SCREEN_OFF_TIMEOUT, -1); - if(timeout != -1) { - writeToLog("setting_screen_timeout " + timeout + "\n"); - } - String httpProxy = Settings.Secure.getString( - context.getContentResolver(), - Settings.Secure.HTTP_PROXY); - if(httpProxy != null) { - writeToLog("setting_httpproxy " + httpProxy + "\n"); - } - } - - /* Let's only grab memory information every 10 seconds to try to keep log - * file size down and the notice_data table size down. - */ - boolean hasMem = false; - if(iter % 10 == 0) { - hasMem = sysInfo.getMemInfo(memInfo); - } - - synchronized(fileWriteLock) { - if(logStream != null) try { - if(firstLogIteration) { - firstLogIteration = false; - logStream.write("time " + System.currentTimeMillis() + "\n"); - Calendar cal = new GregorianCalendar(); - logStream.write("localtime_offset " + - (cal.get(Calendar.ZONE_OFFSET) + - cal.get(Calendar.DST_OFFSET)) + "\n"); - logStream.write("model " + phoneConstants.modelName() + "\n"); - if(NotificationService.available()) { - logStream.write("notifications-active\n"); - } - if(bst.hasFullCapacity()) { - logStream.write("batt_full_capacity " + bst.getFullCapacity() - + "\n"); - } - synchronized(uidAppIds) { - for(int uid : uidAppIds.keySet()) { - if(uid < SystemInfo.AID_APP) { - continue; - } - logStream.write("associate " + uid + " " + uidAppIds.get(uid) - + "\n"); - } - } - } - logStream.write("begin " + iter + "\n"); - logStream.write("total-power " + (long)Math.round(totalPower) + '\n'); - if(hasMem) { - logStream.write("meminfo " + memInfo[0] + " " + memInfo[1] + - " " + memInfo[2] + " " + memInfo[3] + "\n"); - } - for(int i = 0; i < components; i++) { - IterationData data = dataTemp[i]; - if(data != null) { - String name = powerComponents.get(i).getComponentName(); - SparseArray uidData = data.getUidPowerData(); - for(int j = 0; j < uidData.size(); j++) { - int uid = uidData.keyAt(j); - PowerData powerData = uidData.valueAt(j); - if(uid == SystemInfo.AID_ALL) { - logStream.write(name + " " + (long)Math.round( - powerData.getCachedPower()) + "\n"); - powerData.writeLogDataInfo(logStream); - } else { - logStream.write(name + "-" + uid + " " + (long)Math.round( - powerData.getCachedPower()) + "\n"); - } - } - data.recycle(); - } - } - } catch(IOException e) { - Log.w(TAG, "Failed to write to log file"); - } - - if(iter % 15 == 0 && prefs.getBoolean("sendPermission", true)) { - /* Allow for LogUploader to decide if the log needs to be uploaded and - * begin uploading if it decides it's necessary. - */ - if(logUploader.shouldUpload()) { - try { - logStream.close(); - } catch(IOException e) { - Log.w(TAG, "Failed to flush and close log stream"); - } - logStream = null; - logUploader.upload(context.getFileStreamPath( - "PowerTrace.log").getAbsolutePath()); - openLog(false); - firstLogIteration = true; - } - } - } - } - - /* Blank the widget's display and turn off power button. */ - PowerWidget.updateWidgetDone(context); - - /* Have all of the power component threads exit. */ - logUploader.interrupt(); - for(int i = 0; i < components; i++) { - powerComponents.get(i).interrupt(); - } - try { - logUploader.join(); - } catch(InterruptedException e) { - } - for(int i = 0; i < components; i++) { - try { - powerComponents.get(i).join(); - } catch(InterruptedException e) { - } - } - - /* Close the logstream so that everything gets flushed and written to file - * before we have to quit. - */ - synchronized(fileWriteLock) { - if(logStream != null) try { - logStream.close(); - } catch(IOException e) { - Log.w(TAG, "Failed to flush log file on exit"); - } - } - } - - public void plug(boolean plugged) { - logUploader.plug(plugged); - } - - public void writeToLog(String m) { - synchronized(fileWriteLock) { - if(logStream != null) try { - logStream.write(m); - } catch(IOException e) { - Log.w(TAG, "Failed to write message to power log"); - } - } - } - - public String[] getComponents() { - int components = powerComponents.size(); - String[] ret = new String[components]; - for(int i = 0; i < components; i++) { - ret[i] = powerComponents.get(i).getComponentName(); - } - return ret; - } - - public int[] getComponentsMaxPower() { - PhoneConstants constants = PhoneSelector.getConstants(context); - int components = powerComponents.size(); - int[] ret = new int[components]; - for(int i = 0; i < components; i++) { - ret[i] = (int)constants.getMaxPower( - powerComponents.get(i).getComponentName()); - } - return ret; - } - - public int getNoUidMask() { - int components = powerComponents.size(); - int ret = 0; - for(int i = 0; i < components; i++) { - if(!powerComponents.get(i).hasUidInformation()) { - ret |= 1 << i; - } - } - return ret; - } - - public int[] getComponentHistory(int count, int componentId, int uid, - long iteration) { - if(iteration == -1) synchronized(iterationLock) { - iteration = lastWrittenIteration; - } - int components = powerComponents.size(); - if(componentId == ALL_COMPONENTS) { - int[] result = new int[count]; - for(int i = 0; i < components; i++) { - int[] comp = histories.get(i).get(uid, iteration, count); - for(int j = 0; j < count; j++) { - result[j] += comp[j]; - } - } - return result; - } - if(componentId < 0 || components <= componentId) return null; - return histories.get(componentId).get(uid, iteration, count); - } - - public long[] getTotals(int uid, int windowType) { - int components = powerComponents.size(); - long[] ret = new long[components]; - for(int i = 0; i < components; i++) { - ret[i] = histories.get(i).getTotal(uid, windowType) * - ITERATION_INTERVAL / 1000; - } - return ret; - } - - public long getRuntime(int uid, int windowType) { - long runningTime = 0; - int components = powerComponents.size(); - for(int i = 0; i < components; i++) { - long entries = histories.get(i).getCount(uid, windowType); - runningTime = entries > runningTime ? entries : runningTime; - } - return runningTime * ITERATION_INTERVAL / 1000; - } - - public long[] getMeans(int uid, int windowType) { - long[] ret = getTotals(uid, windowType); - long runningTime = getRuntime(uid, windowType); - runningTime = runningTime == 0 ? 1 : runningTime; - for(int i = 0; i < ret.length; i++) { - ret[i] /= runningTime; - } - return ret; - } - - public UidInfo[] getUidInfo(int windowType, int ignoreMask) { - long iteration; - synchronized(iterationLock) { - iteration = lastWrittenIteration; - } - int components = powerComponents.size(); - synchronized(uidAppIds) { - int pos = 0; - UidInfo[] result = new UidInfo[uidAppIds.size()]; - for(Integer uid : uidAppIds.keySet()) { - UidInfo info = UidInfo.obtain(); - int currentPower = 0; - for(int i = 0; i < components; i++) { - if((ignoreMask & 1 << i) == 0) { - currentPower += histories.get(i).get(uid, iteration, 1)[0]; - } - } - double scale = ITERATION_INTERVAL / 1000.0; - info.init(uid, currentPower, - sumArray(getTotals(uid, windowType), ignoreMask) * - ITERATION_INTERVAL / 1000, - getRuntime(uid, windowType) * ITERATION_INTERVAL / 1000); - result[pos++] = info; - } - return result; - } - } - - private long sumArray(long[] A, int ignoreMask) { - long ret = 0; - for(int i = 0; i < A.length; i++) { - if((ignoreMask & 1 << i) == 0) { - ret += A[i]; - } - } - return ret; - } - - public long getUidExtra(String name, int uid) { - if("OLEDSCORE".equals(name)) { - long entries = oledScoreHistory.getCount(uid, Counter.WINDOW_TOTAL); - if(entries <= 0) return -2; - double result = oledScoreHistory.getTotal(uid, Counter.WINDOW_TOTAL) / - 1000.0; - result /= entries; - PhoneConstants phoneConstants = PhoneSelector.getConstants(context); - result *= 255 / (phoneConstants.getMaxPower("OLED") - - phoneConstants.oledBasePower()); - return (long)Math.round(result * 100); - } - return -1; - } -} - diff --git a/src/edu/umich/PowerTutor/ui/PowerTop.java b/src/edu/umich/PowerTutor/ui/PowerTop.java deleted file mode 100644 index 21324f6..0000000 --- a/src/edu/umich/PowerTutor/ui/PowerTop.java +++ /dev/null @@ -1,428 +0,0 @@ -/* -Copyright (C) 2011 The University of Michigan - -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 . - -Please send inquiries to powertutor@umich.edu -*/ - -package edu.umich.PowerTutor.ui; - -import edu.umich.PowerTutor.R; -import edu.umich.PowerTutor.service.ICounterService; -import edu.umich.PowerTutor.service.PowerEstimator; -import edu.umich.PowerTutor.service.UMLoggerService; -import edu.umich.PowerTutor.service.UidInfo; -import edu.umich.PowerTutor.util.Counter; -import edu.umich.PowerTutor.util.Recycler; -import edu.umich.PowerTutor.util.SystemInfo; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.DialogInterface; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.Gravity; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; - -import java.io.ByteArrayInputStream; -import java.io.ObjectInputStream; -import java.io.IOException; -import java.text.DecimalFormat; -import java.util.Arrays; - -public class PowerTop extends Activity implements Runnable { - private static final String TAG = "PowerTop"; - private static final double HIDE_UID_THRESHOLD = 0.1; - - public static final int KEY_CURRENT_POWER = 0; - public static final int KEY_AVERAGE_POWER = 1; - public static final int KEY_TOTAL_ENERGY = 2; - private static final CharSequence[] KEY_NAMES = { "Current power", - "Average power", "Energy usage"}; - - private SharedPreferences prefs; - private int noUidMask; - private String[] componentNames; - - private Intent serviceIntent; - private CounterServiceConnection conn; - private ICounterService counterService; - private Handler handler; - - private LinearLayout topGroup; - private LinearLayout filterGroup; - private LinearLayout mainView; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - prefs = PreferenceManager.getDefaultSharedPreferences(this); - serviceIntent = new Intent(this, UMLoggerService.class); - conn = new CounterServiceConnection(); - if(savedInstanceState != null) { - componentNames = savedInstanceState.getStringArray("componentNames"); - noUidMask = savedInstanceState.getInt("noUidMask"); - } - - topGroup = new LinearLayout(this); - topGroup.setOrientation(LinearLayout.VERTICAL); - ScrollView scrollView = new ScrollView(this); - scrollView.addView(topGroup); - filterGroup = new LinearLayout(this); - filterGroup.setOrientation(LinearLayout.HORIZONTAL); - filterGroup.setMinimumHeight(50); - mainView = new LinearLayout(this); - mainView.setOrientation(LinearLayout.VERTICAL); - mainView.addView(filterGroup); - mainView.addView(scrollView); - } - - @Override - protected void onResume() { - super.onResume(); - handler = new Handler(); - handler.postDelayed(this, 100); - getApplicationContext().bindService(serviceIntent, conn, 0); - - refreshView(); - } - - @Override - protected void onPause() { - super.onPause(); - getApplicationContext().unbindService(conn); - handler.removeCallbacks(this); - handler = null; - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putStringArray("componentNames", componentNames); - outState.putInt("noUidMask", noUidMask); - } - - private static final int MENU_KEY = 0; - private static final int MENU_WINDOW = 1; - private static final int DIALOG_KEY = 0; - private static final int DIALOG_WINDOW = 1; - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - menu.add(0, MENU_KEY, 0, "Display Type"); - menu.add(0, MENU_WINDOW, 0, "Time Span"); - return true; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - /* We need to make sure that the user can't cause any of the dialogs to be - * created before we have contacted the Power Tutor service to get the - * component names and such. - */ - for(int i = 0; i < menu.size(); i++) { - menu.getItem(i).setEnabled(counterService != null); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { - case MENU_KEY: - showDialog(DIALOG_KEY); - return true; - case MENU_WINDOW: - showDialog(DIALOG_WINDOW); - return true; - } - return false; - } - - @Override - protected Dialog onCreateDialog(int id) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - switch(id) { - case DIALOG_KEY: - builder.setTitle("Select sort key"); - builder.setItems(KEY_NAMES, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - prefs.edit().putInt("topKeyId", item).commit(); - } - }); - return builder.create(); - case DIALOG_WINDOW: - builder.setTitle("Select window type"); - builder.setItems(Counter.WINDOW_NAMES, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - prefs.edit().putInt("topWindowType", item).commit(); - } - }); - return builder.create(); - } - return null; - } - - private void refreshView() { - if(counterService == null) { - TextView loadingText = new TextView(this); - loadingText.setText("Waiting for profiler service..."); - loadingText.setGravity(Gravity.CENTER); - setContentView(loadingText); - return; - } - - int keyId = prefs.getInt("topKeyId", KEY_TOTAL_ENERGY); - try { - byte[] rawUidInfo = counterService.getUidInfo( - prefs.getInt("topWindowType", Counter.WINDOW_TOTAL), - noUidMask | prefs.getInt("topIgnoreMask", 0)); - if(rawUidInfo != null) { - UidInfo[] uidInfos = (UidInfo[])new ObjectInputStream( - new ByteArrayInputStream(rawUidInfo)).readObject(); - double total = 0; - for(UidInfo uidInfo : uidInfos) { - if(uidInfo.uid == SystemInfo.AID_ALL) continue; - switch(keyId) { - case KEY_CURRENT_POWER: - uidInfo.key = uidInfo.currentPower; - uidInfo.unit = "W"; - break; - case KEY_AVERAGE_POWER: - uidInfo.key = uidInfo.totalEnergy / - (uidInfo.runtime == 0 ? 1 : uidInfo.runtime); - uidInfo.unit = "W"; - break; - case KEY_TOTAL_ENERGY: - uidInfo.key = uidInfo.totalEnergy; - uidInfo.unit = "J"; - break; - default: - uidInfo.key = uidInfo.currentPower; - uidInfo.unit = "W"; - } - total += uidInfo.key; - } - if(total == 0) total = 1; - for(UidInfo uidInfo : uidInfos) { - uidInfo.percentage = 100.0 * uidInfo.key / total; - } - Arrays.sort(uidInfos); - - int sz = 0; - for(int i = 0; i < uidInfos.length; i++) { - if(uidInfos[i].uid == SystemInfo.AID_ALL || - uidInfos[i].percentage < HIDE_UID_THRESHOLD) { - continue; - } - UidPowerView powerView; - if(sz < topGroup.getChildCount()) { - powerView = (UidPowerView)topGroup.getChildAt(sz); - } else { - powerView = UidPowerView.obtain(this, getIntent()); - topGroup.addView(powerView); - } - powerView.setBackgroundDrawable(null); - powerView.setBackgroundColor((sz & 1) == 0 ? 0xFF000000 : - 0xFF222222); - powerView.init(uidInfos[i], keyId); - sz++; - } - for(int i = sz; i < topGroup.getChildCount(); i++) { - UidPowerView powerView = (UidPowerView)topGroup.getChildAt(i); - powerView.recycle(); - } - topGroup.removeViews(sz, topGroup.getChildCount() - sz); - } - } catch(IOException e) { - } catch(RemoteException e) { - } catch(ClassNotFoundException e) { - } catch(ClassCastException e) { - } - setContentView(mainView); - if(keyId == KEY_CURRENT_POWER) { - setTitle(KEY_NAMES[keyId]); - } else { - setTitle(KEY_NAMES[keyId] + " over " + - Counter.WINDOW_DESCS[prefs.getInt("topWindowType", - Counter.WINDOW_TOTAL)]); - } - } - - public void run() { - refreshView(); - if(handler != null) { - handler.postDelayed(this, 2 * PowerEstimator.ITERATION_INTERVAL); - } - } - - private static class UidPowerView extends LinearLayout { - private static Recycler recycler = - new Recycler(); - private static DecimalFormat formatter = new DecimalFormat("0.0"); - - public static UidPowerView obtain(Activity activity, Intent startIntent) { - UidPowerView result = recycler.obtain(); - if(result == null) return new UidPowerView(activity, startIntent); - return result; - } - - public void recycle() { - recycler.recycle(this); - } - - private UidInfo uidInfo; - private String name; - private Drawable icon; - - private ImageView imageView; - private TextView textView; - - private UidPowerView(final Activity activity, final Intent startIntent) { - super(activity); - setMinimumHeight(50); - setOrientation(LinearLayout.HORIZONTAL); - imageView = new ImageView(activity); - imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - imageView.setAdjustViewBounds(true); - imageView.setMaxHeight(40); - imageView.setMaxWidth(40); - imageView.setMinimumWidth(50); - imageView.setLayoutParams(new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.FILL_PARENT)); - textView = new TextView(activity); - textView.setGravity(Gravity.CENTER_VERTICAL); - textView.setLayoutParams(new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT)); - addView(imageView); - addView(textView); - setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - Intent viewIntent = new Intent(v.getContext(), PowerTabs.class); - viewIntent.putExtras(startIntent); - viewIntent.putExtra("uid", uidInfo.uid); - activity.startActivityForResult(viewIntent, 0); - } - }); - setFocusable(true); - } - - public void init(UidInfo uidInfo, int keyType) { - SystemInfo sysInfo = SystemInfo.getInstance(); - this.uidInfo = uidInfo; - PackageManager pm = getContext().getPackageManager(); - name = sysInfo.getUidName(uidInfo.uid, pm); - icon = sysInfo.getUidIcon(uidInfo.uid, pm); - imageView.setImageDrawable(icon); - String prefix; - if(uidInfo.key > 1e12) { - prefix = "G"; - uidInfo.key /= 1e12; - } else if(uidInfo.key > 1e9) { - prefix = "M"; - uidInfo.key /= 1e9; - } else if(uidInfo.key > 1e6) { - prefix = "k"; - uidInfo.key /= 1e6; - } else if(uidInfo.key > 1e3) { - prefix = ""; - uidInfo.key /= 1e3; - } else { - prefix = "m"; - } - long secs = (long)Math.round(uidInfo.runtime); - - textView.setText(String.format("%1$.1f%% [%3$d:%4$02d:%5$02d] %2$s\n" + - "%6$.1f %7$s%8$s", - uidInfo.percentage, name, secs / 60 / 60, (secs / 60) % 60, - secs % 60, uidInfo.key, prefix, uidInfo.unit)); - } - } - - private class CounterServiceConnection implements ServiceConnection { - public void onServiceConnected(ComponentName className, - IBinder boundService ) { - counterService = ICounterService.Stub.asInterface((IBinder)boundService); - try { - componentNames = counterService.getComponents(); - noUidMask = counterService.getNoUidMask(); - filterGroup.removeAllViews(); - for(int i = 0; i < componentNames.length; i++) { - int ignMask = prefs.getInt("topIgnoreMask", 0); - if((noUidMask & 1 << i) != 0) continue; - final TextView filterToggle = new TextView(PowerTop.this); - final int index = i; - filterToggle.setText(componentNames[i]); - filterToggle.setGravity(Gravity.CENTER); - filterToggle.setTextColor((ignMask & 1 << index) == 0 ? - 0xFFFFFFFF : 0xFF888888); - filterToggle.setBackgroundColor( - filterGroup.getChildCount() % 2 == 0 ? 0xFF444444 : 0xFF555555); - filterToggle.setFocusable(true); - filterToggle.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - int ignMask = prefs.getInt("topIgnoreMask", 0); - if((ignMask & 1 << index) == 0) { - prefs.edit().putInt("topIgnoreMask", ignMask | 1 << index) - .commit(); - filterToggle.setTextColor(0xFF888888); - } else { - prefs.edit().putInt("topIgnoreMask", ignMask & ~(1 << index)) - .commit(); - filterToggle.setTextColor(0xFFFFFFFF); - } - } - }); - filterGroup.addView(filterToggle, - new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT, 1f)); - } - } catch(RemoteException e) { - counterService = null; - } - } - - public void onServiceDisconnected(ComponentName className) { - counterService = null; - getApplicationContext().unbindService(conn); - getApplicationContext().bindService(serviceIntent, conn, 0); - Log.w(TAG, "Unexpectedly lost connection to service"); - } - } -} - diff --git a/src/edu/umich/PowerTutor/ui/PowerViewer.java b/src/edu/umich/PowerTutor/ui/PowerViewer.java deleted file mode 100644 index d0c0d96..0000000 --- a/src/edu/umich/PowerTutor/ui/PowerViewer.java +++ /dev/null @@ -1,350 +0,0 @@ -/* -Copyright (C) 2011 The University of Michigan - -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 . - -Please send inquiries to powertutor@umich.edu -*/ - -package edu.umich.PowerTutor.ui; - -import org.achartengine.GraphicalView; -import org.achartengine.chart.CubicLineChart; -import org.achartengine.model.XYMultipleSeriesDataset; -import org.achartengine.model.XYSeries; -import org.achartengine.renderer.XYMultipleSeriesRenderer; -import org.achartengine.renderer.XYSeriesRenderer; - -import android.app.Activity; -import android.content.ComponentName; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.SystemClock; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.Gravity; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; -import edu.umich.PowerTutor.service.ICounterService; -import edu.umich.PowerTutor.service.PowerEstimator; -import edu.umich.PowerTutor.service.UMLoggerService; -import edu.umich.PowerTutor.util.SystemInfo; - -public class PowerViewer extends Activity { - private static final String TAG = "PowerViewer"; - - private SharedPreferences prefs; - private int uid; - - private int components; - private String[] componentNames; - private int[] componentsMaxPower; - private int noUidMask; - private boolean collecting; - - private ValueCollector[] collectors; - - private Intent serviceIntent; - private CounterServiceConnection conn; - private ICounterService counterService; - - private Handler handler; - private LinearLayout chartLayout; - - public void refreshView() { - if(counterService == null) { - TextView loadingText = new TextView(this); - loadingText.setText("Waiting for profiler service..."); - loadingText.setGravity(Gravity.CENTER); - setContentView(loadingText); - return; - } - - chartLayout = new LinearLayout(this); - chartLayout.setOrientation(LinearLayout.VERTICAL); - - if(uid == SystemInfo.AID_ALL) { - /* If we are reporting global power usage then just set noUidMask to 0 so - * that all components get displayed. - */ - noUidMask = 0; - } - components = 0; - for(int i = 0; i < componentNames.length; i++) { - if((noUidMask & 1 << i) == 0) { - components++; - } - } - boolean showTotal = prefs.getBoolean("showTotalPower", false); - collectors = new ValueCollector[(showTotal ? 1 : 0) + components]; - - int pos = 0; - for(int i = showTotal ? -1 : 0; i < componentNames.length; i++) { - if(i != -1 && (noUidMask & 1 << i) != 0) { - continue; - } - String name = i == -1 ? "Total" : componentNames[i]; - double mxPower = (i == -1 ? 2100.0 : componentsMaxPower[i]) * 1.05; - - XYSeries series = new XYSeries(name); - XYMultipleSeriesDataset mseries = new XYMultipleSeriesDataset(); - mseries.addSeries(series); - - XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer(); - XYSeriesRenderer srenderer = new XYSeriesRenderer(); - renderer.setYAxisMin(0.0); - renderer.setYAxisMax(mxPower); - renderer.setYTitle(name + "(mW)"); - - int clr = PowerPie.COLORS[(PowerPie.COLORS.length + i) % - PowerPie.COLORS.length]; - srenderer.setColor(clr); - srenderer.setFillBelowLine(true); - srenderer.setFillBelowLineColor(((clr >> 1) & 0x7F7F7F) | - (clr & 0xFF000000)); - renderer.addSeriesRenderer(srenderer); - - View chartView = new GraphicalView(this, - new CubicLineChart(mseries, renderer, 0.5f)); - chartView.setMinimumHeight(100); - chartLayout.addView(chartView); - - collectors[pos] = new ValueCollector(series, renderer, chartView, i); - if(handler != null) { - handler.post(collectors[pos]); - } - pos++; - } - - /* We're giving 100 pixels per graph of vertical space for the chart view. - If we don't specify a minimum height the chart view ends up having a - height of 0 so this is important. */ - chartLayout.setMinimumHeight(100 * components); - - ScrollView scrollView = new ScrollView(this) { - public boolean onInterceptTouchEvent(android.view.MotionEvent ev) { - return true; - } - }; - - scrollView.addView(chartLayout); - scrollView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); - setContentView(scrollView); - } - - private class CounterServiceConnection implements ServiceConnection { - public void onServiceConnected(ComponentName className, - IBinder boundService) { - counterService = ICounterService.Stub.asInterface((IBinder)boundService); - try { - componentNames = counterService.getComponents(); - componentsMaxPower = counterService.getComponentsMaxPower(); - noUidMask = counterService.getNoUidMask(); - refreshView(); - } catch(RemoteException e) { - counterService = null; - } - } - - public void onServiceDisconnected(ComponentName className) { - counterService = null; - getApplicationContext().unbindService(conn); - getApplicationContext().bindService(serviceIntent, conn, 0); - Log.w(TAG, "Unexpectedly lost connection to service"); - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - prefs = PreferenceManager.getDefaultSharedPreferences(this); - uid = getIntent().getIntExtra("uid", SystemInfo.AID_ALL); - - collecting = true; - if(savedInstanceState != null) { - collecting = savedInstanceState.getBoolean("collecting", true); - componentNames = savedInstanceState.getStringArray("componentNames"); - noUidMask = savedInstanceState.getInt("noUidMask"); - } - - serviceIntent = new Intent(this, UMLoggerService.class); - conn = new CounterServiceConnection(); - } - - @Override - protected void onResume() { - super.onResume(); - handler = new Handler(); - getApplicationContext().bindService(serviceIntent, conn, 0); - - refreshView(); - } - - @Override - protected void onPause() { - super.onPause(); - getApplicationContext().unbindService(conn); - if(collectors != null) for(int i = 0; i < components; i++) { - handler.removeCallbacks(collectors[i]); - } - counterService = null; - handler = null; - collecting = true; - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean("collecting", collecting); - outState.putStringArray("componentNames", componentNames); - outState.putInt("noUidMask", noUidMask); - } - - /* Let all of the UI graphs lay themselves out again. */ - private void stateChanged() { - for(int i = 0; i < components; i++) { - collectors[i].layout(); - } - } - - private static final int MENU_OPTIONS = 0; - private static final int MENU_TOGGLE_COLLECTING = 1; - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - menu.add(0, MENU_OPTIONS, 0, "Options"); - menu.add(0, MENU_TOGGLE_COLLECTING, 0, ""); - return true; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - menu.findItem(MENU_TOGGLE_COLLECTING).setTitle( - collecting ? "Pause" : "Resume"); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { - case MENU_OPTIONS: - startActivity(new Intent(this, ViewerPreferences.class)); - return true; - case MENU_TOGGLE_COLLECTING: - collecting = !collecting; - if(handler != null) { - if(collecting) for(int i = 0; i < components; i++) { - collectors[i].reset(); - handler.post(collectors[i]); - } else for(int i = 0; i < components; i++) { - handler.removeCallbacks(collectors[i]); - } - } - break; - } - return false; - } - - public class ValueCollector implements Runnable { - private XYSeries series; - private XYMultipleSeriesRenderer renderer; - private View chartView; - - private int componentId; - private long lastTime; - - int[] values; - - private boolean readHistory; - - public ValueCollector(XYSeries series, XYMultipleSeriesRenderer renderer, - View chartView, int componentId) { - this.series = series; - this.renderer = renderer; - this.chartView = chartView; - this.componentId = componentId; - lastTime = SystemClock.elapsedRealtime(); - layout(); - } - - public void layout() { - int numVals = Integer.parseInt(prefs.getString("viewNumValues_s", "60")); - values = new int[numVals]; - - renderer.clearXTextLabels(); - renderer.setXAxisMin(0); - renderer.setXAxisMax(numVals - 1); - renderer.addXTextLabel(numVals - 1, "" + numVals); - renderer.setXLabels(0); - for(int j = 0; j < 10; j++) { - renderer.addXTextLabel(numVals * j / 10, "" + (1 + numVals * j / 10)); - } - - reset(); - } - - /** Restart points collecting from zero. */ - public void reset() { - series.clear(); - readHistory = true; - } - - public void run() { - int numVals = Integer.parseInt(prefs.getString("viewNumValues_s", "60")); - if(counterService != null) try { - if(readHistory) { - values = counterService.getComponentHistory(numVals, - componentId, uid); - readHistory = false; - } else { - for(int i = numVals - 1; i > 0; i--) { - values[i] = values[i - 1]; - } - values[0] = counterService.getComponentHistory(1, componentId, - uid)[0]; - } - } catch(RemoteException e) { - Log.w(TAG, "Failed to get data from service"); - for(int i = 0; i < numVals; i++) { - values[i] = 0; - } - } - - series.clear(); - for(int i = 0; i < numVals; i++) { - series.add(i, values[i]); - } - - long curTime = SystemClock.elapsedRealtime(); - long tryTime = lastTime + PowerEstimator.ITERATION_INTERVAL * - (long)Math.max(1, 1 + (curTime - lastTime) / - PowerEstimator.ITERATION_INTERVAL); - if(handler != null) { - handler.postDelayed(this, tryTime - curTime); - } - - chartView.invalidate(); - } - }; -} diff --git a/src/edu/umich/PowerTutor/ui/UMLogger.java b/src/edu/umich/PowerTutor/ui/UMLogger.java deleted file mode 100644 index ebaca34..0000000 --- a/src/edu/umich/PowerTutor/ui/UMLogger.java +++ /dev/null @@ -1,355 +0,0 @@ -/* -Copyright (C) 2011 The University of Michigan - -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 . - -Please send inquiries to powertutor@umich.edu -*/ - -package edu.umich.PowerTutor.ui; - -import edu.umich.PowerTutor.R; -import edu.umich.PowerTutor.phone.PhoneSelector; -import edu.umich.PowerTutor.service.ICounterService; -import edu.umich.PowerTutor.service.UMLoggerService; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.Environment; -import android.os.IBinder; -import android.os.RemoteException; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -import java.io.File; -import java.io.FileOutputStream; -import java.util.zip.InflaterInputStream; -import java.io.BufferedOutputStream; - -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** The main view activity for PowerTutor*/ -public class UMLogger extends Activity { - private static final String TAG = "UMLogger"; - - public static final String CURRENT_VERSION = "1.2"; // Don't change this... - - public static final String SERVER_IP = "spidermonkey.eecs.umich.edu"; - public static final int SERVER_PORT = 5204; - - private SharedPreferences prefs; - private Intent serviceIntent; - private ICounterService counterService; - private CounterServiceConnection conn; - - private Button serviceStartButton; - private Button appViewerButton; - private Button sysViewerButton; - private Button helpButton; - private TextView scaleText; - - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - prefs = PreferenceManager.getDefaultSharedPreferences(this); - serviceIntent = new Intent(this, UMLoggerService.class); - conn = new CounterServiceConnection(); - - setContentView(R.layout.main); - ArrayAdapter adapterxaxis = ArrayAdapter.createFromResource( - this, R.array.xaxis, android.R.layout.simple_spinner_item); - adapterxaxis.setDropDownViewResource( - android.R.layout.simple_spinner_dropdown_item); - - serviceStartButton = (Button)findViewById(R.id.servicestartbutton); - appViewerButton = (Button)findViewById(R.id.appviewerbutton); - sysViewerButton = (Button)findViewById(R.id.sysviewerbutton); - helpButton= (Button)findViewById(R.id.helpbutton); - - serviceStartButton.setOnClickListener(serviceStartButtonListener); - sysViewerButton.setOnClickListener(sysViewerButtonListener); - appViewerButton.setOnClickListener(appViewerButtonListener); - helpButton.setOnClickListener(helpButtonListener); - - if(counterService != null) { - serviceStartButton.setText("Stop Profiler"); - appViewerButton.setEnabled(true); - sysViewerButton.setEnabled(true); - } else { - serviceStartButton.setText("Start Profiler"); - appViewerButton.setEnabled(false); - sysViewerButton.setEnabled(false); - } - } - - @Override - public void onResume() { - super.onResume(); - getApplicationContext().bindService(serviceIntent, conn, 0); - if(prefs.getBoolean("firstRun", true)) { - if(PhoneSelector.getPhoneType() == PhoneSelector.PHONE_UNKNOWN) { - showDialog(DIALOG_UNKNOWN_PHONE); - } else { - showDialog(DIALOG_TOS); - } - } - Intent startingIntent = getIntent(); - if(startingIntent.getBooleanExtra("isFromIcon", false)) { - Intent copyIntent = (Intent)getIntent().clone(); - copyIntent.putExtra("isFromIcon", false); - setIntent(copyIntent); - Intent intent = new Intent(this, PowerTabs.class); - startActivity(intent); - } - } - - @Override - public void onPause() { - super.onPause(); - getApplicationContext().unbindService(conn); - } - - private static final int MENU_PREFERENCES = 0; - private static final int MENU_SAVE_LOG = 1; - private static final int DIALOG_START_SENDING = 0; - private static final int DIALOG_STOP_SENDING = 1; - private static final int DIALOG_TOS = 2; - private static final int DIALOG_RUNNING_ON_STARTUP = 3; - private static final int DIALOG_NOT_RUNNING_ON_STARTUP = 4; - private static final int DIALOG_UNKNOWN_PHONE = 5; - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - menu.add(0, MENU_PREFERENCES, 0, "Options"); - menu.add(0, MENU_SAVE_LOG, 0, "Save log"); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { - case MENU_PREFERENCES: - startActivity(new Intent(this, EditPreferences.class)); - return true; - case MENU_SAVE_LOG: - new Thread() { - public void start() { - File writeFile = new File( - Environment.getExternalStorageDirectory(), "PowerTrace" + - System.currentTimeMillis() + ".log"); - try { - InflaterInputStream logIn = new InflaterInputStream( - openFileInput("PowerTrace.log")); - BufferedOutputStream logOut = new BufferedOutputStream( - new FileOutputStream(writeFile)); - - byte[] buffer = new byte[20480]; - for(int ln = logIn.read(buffer); ln != -1; - ln = logIn.read(buffer)) { - logOut.write(buffer, 0, ln); - } - logIn.close(); - logOut.close(); - Toast.makeText(UMLogger.this, "Wrote log to " + - writeFile.getAbsolutePath(), - Toast.LENGTH_SHORT).show(); - return; - } catch(java.io.EOFException e) { - Toast.makeText(UMLogger.this, "Wrote log to " + - writeFile.getAbsolutePath(), - Toast.LENGTH_SHORT).show(); - return; - } catch(IOException e) { - } - Toast.makeText(UMLogger.this, "Failed to write log to sdcard", - Toast.LENGTH_SHORT).show(); - } - }.start(); - return true; - } - return super.onOptionsItemSelected(item); - } - - /**This function includes all the dialog constructor*/ - @Override - protected Dialog onCreateDialog(int id) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - switch(id) { - case DIALOG_TOS: - builder.setMessage(R.string.term) - .setCancelable(false) - .setPositiveButton("Agree", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - prefs.edit().putBoolean("firstRun", false) - .putBoolean("runOnStartup", true) - .putBoolean("sendPermission", true).commit(); - dialog.dismiss(); - } - }) - .setNegativeButton("Do not agree", - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - prefs.edit().putBoolean("firstRun", true).commit(); - finish(); - } - }); - return builder.create(); - case DIALOG_STOP_SENDING: - builder.setMessage(R.string.stop_sending_text) - .setCancelable(true) - .setPositiveButton("Stop", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - prefs.edit().putBoolean("sendPermission", false).commit(); - dialog.dismiss(); - } - }) - .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - return builder.create(); - case DIALOG_START_SENDING: - builder.setMessage(R.string.start_sending_text) - .setCancelable(true) - .setPositiveButton("Start", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - prefs.edit().putBoolean("sendPermission", true).commit(); - dialog.dismiss(); - } - }) - .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - return builder.create(); - case DIALOG_RUNNING_ON_STARTUP: - builder.setMessage(R.string.running_on_startup) - .setCancelable(true) - .setNeutralButton("Ok", null); - return builder.create(); - case DIALOG_NOT_RUNNING_ON_STARTUP: - builder.setMessage(R.string.not_running_on_startup) - .setCancelable(true) - .setNeutralButton("Ok", null); - return builder.create(); - case DIALOG_UNKNOWN_PHONE: - builder.setMessage(R.string.unknown_phone) - .setCancelable(false) - .setNeutralButton("Ok", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - showDialog(DIALOG_TOS); - } - }); - return builder.create(); - - } - return null; - } - - - private Button.OnClickListener appViewerButtonListener = - new Button.OnClickListener() { - public void onClick(View v) { - Intent intent = new Intent(v.getContext(), PowerTop.class); - startActivityForResult(intent, 0); - } - }; - - private Button.OnClickListener sysViewerButtonListener = - new Button.OnClickListener() { - public void onClick(View v) { - Intent intent = new Intent(v.getContext(), PowerTabs.class); - startActivityForResult(intent, 0); - } - }; - - private Button.OnClickListener serviceStartButtonListener = - new Button.OnClickListener() { - public void onClick(View v) { - serviceStartButton.setEnabled(false); - if(counterService != null) { - stopService(serviceIntent); - } else { - if(conn == null) { - Toast.makeText(UMLogger.this, "Profiler failed to start", - Toast.LENGTH_SHORT).show(); - } else { - startService(serviceIntent); - } - } - } - }; - - private class CounterServiceConnection implements ServiceConnection { - public void onServiceConnected(ComponentName className, - IBinder boundService) { - counterService = ICounterService.Stub.asInterface((IBinder)boundService); - serviceStartButton.setText("Stop Profiler"); - serviceStartButton.setEnabled(true); - appViewerButton.setEnabled(true); - sysViewerButton.setEnabled(true); - } - - public void onServiceDisconnected(ComponentName className) { - counterService = null; - getApplicationContext().unbindService(conn); - getApplicationContext().bindService(serviceIntent, conn, 0); - - Toast.makeText(UMLogger.this, "Profiler stopped", - Toast.LENGTH_SHORT).show(); - serviceStartButton.setText("Start Profiler"); - serviceStartButton.setEnabled(true); - appViewerButton.setEnabled(false); - sysViewerButton.setEnabled(false); - } - } - - private Button.OnClickListener helpButtonListener = - new Button.OnClickListener() { - public void onClick(View v) { - Intent myIntent = new Intent(v.getContext(), Help.class); - startActivityForResult(myIntent, 0); - } - }; -}