Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

Commit 56d85fa

Browse files
committed
Merge pull request #1130 from dodgex/863_WakeLock
@Wakelock
2 parents 3512756 + 869bc00 commit 56d85fa

10 files changed

Lines changed: 424 additions & 26 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* Copyright (C) 2010-2014 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.annotations;
17+
18+
import java.lang.annotation.ElementType;
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
21+
import java.lang.annotation.Target;
22+
23+
/**
24+
* <p>
25+
* Acquires a {@link android.os.PowerManager.WakeLock} for this method call.
26+
* </p>
27+
* <p>
28+
* May be used on methods with @Background or @UiThread.
29+
* </p>
30+
* <p>
31+
* <b>NOTE</b>: To use WakeLocks you need the
32+
* {@link android.permission.WAKE_LOCK} permission.
33+
* </p>
34+
*
35+
* <b>Example</b>:
36+
*
37+
* <pre>
38+
* &#064;EActivity
39+
* public class MyActivity extends Acitivy {
40+
*
41+
* &#064;WakeLock
42+
* void backgroundTask() {
43+
* // this code executes with an active WakeLock.
44+
* }
45+
* }
46+
* </pre>
47+
*
48+
* @see android.os.PowerManager
49+
* @see android.os.PowerManager.WakeLock
50+
*/
51+
@Retention(RetentionPolicy.CLASS)
52+
@Target(ElementType.METHOD)
53+
public @interface WakeLock {
54+
55+
String DEFAULT_TAG = "NO_TAG";
56+
57+
String tag() default DEFAULT_TAG;
58+
59+
Level level() default Level.PARTIAL_WAKE_LOCK;
60+
61+
Flag[] flags() default {};
62+
63+
public enum Level {
64+
/**
65+
* @see android.os.PowerManager.FULL_WAKE_LOCK
66+
*/
67+
FULL_WAKE_LOCK,
68+
69+
/**
70+
* @see android.os.PowerManager.PARTIAL_WAKE_LOCK
71+
*/
72+
PARTIAL_WAKE_LOCK,
73+
74+
/**
75+
* @see android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK
76+
*/
77+
SCREEN_BRIGHT_WAKE_LOCK,
78+
79+
/**
80+
* @see android.os.PowerManager.SCREEN_DIM_WAKE_LOCK
81+
*/
82+
SCREEN_DIM_WAKE_LOCK;
83+
}
84+
85+
public enum Flag {
86+
/**
87+
* @see android.os.PowerManager.ACQUIRE_CAUSES_WAKEUP
88+
*/
89+
ACQUIRE_CAUSES_WAKEUP,
90+
91+
/**
92+
* @see android.os.PowerManager.ON_AFTER_RELEASE
93+
*/
94+
ON_AFTER_RELEASE
95+
}
96+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/AnnotationHandlers.java‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ public AnnotationHandlers(ProcessingEnvironment processingEnvironment) {
129129
if (optionsHelper.shouldLogTrace()) {
130130
add(new TraceHandler(processingEnvironment));
131131
}
132+
133+
/*
134+
* WakeLockHandler must be after TraceHandler but before UiThreadHandler
135+
* and BackgroundHandler
136+
*/
137+
add(new WakeLockHandler(processingEnvironment));
138+
132139
/*
133140
* UIThreadHandler and BackgroundHandler must be after TraceHandler and
134141
* IgnoredWhenDetached
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/**
2+
* Copyright (C) 2010-2014 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.handler;
17+
18+
import javax.annotation.processing.ProcessingEnvironment;
19+
import javax.lang.model.element.Element;
20+
import javax.lang.model.element.ExecutableElement;
21+
22+
import org.androidannotations.annotations.WakeLock;
23+
import org.androidannotations.annotations.WakeLock.Flag;
24+
import org.androidannotations.annotations.WakeLock.Level;
25+
import org.androidannotations.helper.APTCodeModelHelper;
26+
import org.androidannotations.holder.EComponentHolder;
27+
import org.androidannotations.model.AnnotationElements;
28+
import org.androidannotations.process.IsValid;
29+
30+
import com.sun.codemodel.JBlock;
31+
import com.sun.codemodel.JConditional;
32+
import com.sun.codemodel.JExpr;
33+
import com.sun.codemodel.JExpression;
34+
import com.sun.codemodel.JInvocation;
35+
import com.sun.codemodel.JMethod;
36+
import com.sun.codemodel.JTryBlock;
37+
import com.sun.codemodel.JVar;
38+
39+
public class WakeLockHandler extends BaseAnnotationHandler<EComponentHolder> {
40+
41+
private final APTCodeModelHelper codeModelHelper = new APTCodeModelHelper();
42+
43+
public WakeLockHandler(ProcessingEnvironment processingEnvironment) {
44+
super(WakeLock.class, processingEnvironment);
45+
}
46+
47+
@Override
48+
public void validate(Element element, AnnotationElements validatedElements, IsValid valid) {
49+
validatorHelper.enclosingElementHasEnhancedComponentAnnotation(element, validatedElements, valid);
50+
51+
ExecutableElement executableElement = (ExecutableElement) element;
52+
validatorHelper.doesNotHaveTraceAnnotationAndReturnValue(executableElement, validatedElements, valid);
53+
54+
validatorHelper.doesNotUseFlagsWithPartialWakeLock(element, validatedElements, valid);
55+
56+
validatorHelper.hasWakeLockPermission(element, androidManifest, valid);
57+
58+
validatorHelper.isNotPrivate(element, valid);
59+
60+
validatorHelper.isNotFinal(element, valid);
61+
62+
}
63+
64+
@Override
65+
public void process(Element element, EComponentHolder holder) {
66+
ExecutableElement executableElement = (ExecutableElement) element;
67+
WakeLock annotation = executableElement.getAnnotation(WakeLock.class);
68+
69+
String tag = extractTag(executableElement);
70+
Level level = annotation.level();
71+
Flag[] flags = annotation.flags();
72+
73+
JMethod method = codeModelHelper.overrideAnnotatedMethod(executableElement, holder);
74+
JBlock previousMethodBody = codeModelHelper.removeBody(method);
75+
76+
JBlock methodBody = method.body();
77+
78+
JExpression levelAndFlags = classes().POWER_MANAGER.staticRef(level.name());
79+
if (flags.length > 0) {
80+
for (Flag flag : flags) {
81+
levelAndFlags = levelAndFlags.bor(classes().POWER_MANAGER.staticRef(flag.name()));
82+
}
83+
}
84+
85+
JInvocation newWakeLock = holder.getPowerManagerRef().invoke("newWakeLock").arg(levelAndFlags).arg(JExpr.lit(tag));
86+
87+
JVar wakeLock = methodBody.decl(classes().WAKE_LOCK, "wakeLock", JExpr._null());
88+
89+
JTryBlock tryBlock = methodBody._try();
90+
tryBlock.body().assign(wakeLock, newWakeLock);
91+
tryBlock.body().add(wakeLock.invoke("acquire"));
92+
tryBlock.body().add(previousMethodBody);
93+
94+
JBlock finallyBlock = tryBlock._finally();
95+
JConditional _if = finallyBlock._if(wakeLock.ne(JExpr._null()));
96+
_if._then().add(wakeLock.invoke("release"));
97+
}
98+
99+
private String extractTag(Element element) {
100+
WakeLock annotation = element.getAnnotation(WakeLock.class);
101+
String tag = annotation.tag();
102+
if (WakeLock.DEFAULT_TAG.equals(tag)) {
103+
tag = element.getEnclosingElement().getSimpleName().toString() + "." + element.getSimpleName().toString();
104+
}
105+
return tag;
106+
}
107+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/CanonicalNameConstants.java‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,14 @@ public final class CanonicalNameConstants {
105105
public static final String SQLLITE_OPEN_HELPER = "android.database.sqlite.SQLiteOpenHelper";
106106
public static final String VIEW_SERVER = "org.androidannotations.api.ViewServer";
107107
public static final String LOOPER = "android.os.Looper";
108+
public static final String POWER_MANAGER = "android.os.PowerManager";
109+
public static final String WAKE_LOCK = "android.os.PowerManager.WakeLock";
108110

109111
/*
110112
* Android permission
111113
*/
112114
public static final String INTERNET_PERMISSION = "android.permission.INTERNET";
115+
public static final String WAKELOCK_PERMISSION = "android.permission.WAKE_LOCK";
113116

114117
/*
115118
* Sherlock

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/ValidatorHelper.java‎

Lines changed: 94 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,70 @@
1515
*/
1616
package org.androidannotations.helper;
1717

18-
import org.androidannotations.annotations.*;
19-
import org.androidannotations.annotations.rest.*;
20-
import org.androidannotations.annotations.sharedpreferences.*;
18+
import static java.util.Arrays.asList;
19+
import static org.androidannotations.helper.AndroidConstants.LOG_DEBUG;
20+
import static org.androidannotations.helper.AndroidConstants.LOG_ERROR;
21+
import static org.androidannotations.helper.AndroidConstants.LOG_INFO;
22+
import static org.androidannotations.helper.AndroidConstants.LOG_VERBOSE;
23+
import static org.androidannotations.helper.AndroidConstants.LOG_WARN;
24+
import static org.androidannotations.helper.CanonicalNameConstants.CLIENT_HTTP_REQUEST_FACTORY;
25+
import static org.androidannotations.helper.CanonicalNameConstants.CLIENT_HTTP_REQUEST_INTERCEPTOR;
26+
import static org.androidannotations.helper.CanonicalNameConstants.HTTP_MESSAGE_CONVERTER;
27+
import static org.androidannotations.helper.CanonicalNameConstants.INTERNET_PERMISSION;
28+
import static org.androidannotations.helper.CanonicalNameConstants.WAKELOCK_PERMISSION;
29+
import static org.androidannotations.helper.ModelConstants.GENERATION_SUFFIX;
30+
import static org.androidannotations.helper.ModelConstants.VALID_ANDROID_ANNOTATIONS;
31+
import static org.androidannotations.helper.ModelConstants.VALID_ENHANCED_COMPONENT_ANNOTATIONS;
32+
import static org.androidannotations.helper.ModelConstants.VALID_ENHANCED_VIEW_SUPPORT_ANNOTATIONS;
33+
34+
import java.lang.annotation.Annotation;
35+
import java.util.ArrayList;
36+
import java.util.Arrays;
37+
import java.util.Collection;
38+
import java.util.HashMap;
39+
import java.util.List;
40+
import java.util.Map;
41+
import java.util.Set;
42+
import java.util.TreeSet;
43+
44+
import javax.lang.model.element.AnnotationMirror;
45+
import javax.lang.model.element.Element;
46+
import javax.lang.model.element.ElementKind;
47+
import javax.lang.model.element.ExecutableElement;
48+
import javax.lang.model.element.Modifier;
49+
import javax.lang.model.element.TypeElement;
50+
import javax.lang.model.element.VariableElement;
51+
import javax.lang.model.type.ArrayType;
52+
import javax.lang.model.type.DeclaredType;
53+
import javax.lang.model.type.ErrorType;
54+
import javax.lang.model.type.TypeKind;
55+
import javax.lang.model.type.TypeMirror;
56+
import javax.lang.model.util.ElementFilter;
57+
import javax.lang.model.util.Elements;
58+
59+
import org.androidannotations.annotations.EActivity;
60+
import org.androidannotations.annotations.EBean;
61+
import org.androidannotations.annotations.EFragment;
62+
import org.androidannotations.annotations.EIntentService;
63+
import org.androidannotations.annotations.EService;
64+
import org.androidannotations.annotations.Receiver;
65+
import org.androidannotations.annotations.Trace;
66+
import org.androidannotations.annotations.ViewById;
67+
import org.androidannotations.annotations.WakeLock;
68+
import org.androidannotations.annotations.WakeLock.Level;
69+
import org.androidannotations.annotations.rest.Delete;
70+
import org.androidannotations.annotations.rest.Get;
71+
import org.androidannotations.annotations.rest.Head;
72+
import org.androidannotations.annotations.rest.Options;
73+
import org.androidannotations.annotations.rest.Post;
74+
import org.androidannotations.annotations.rest.Put;
75+
import org.androidannotations.annotations.rest.Rest;
76+
import org.androidannotations.annotations.sharedpreferences.DefaultBoolean;
77+
import org.androidannotations.annotations.sharedpreferences.DefaultFloat;
78+
import org.androidannotations.annotations.sharedpreferences.DefaultInt;
79+
import org.androidannotations.annotations.sharedpreferences.DefaultLong;
80+
import org.androidannotations.annotations.sharedpreferences.DefaultString;
81+
import org.androidannotations.annotations.sharedpreferences.SharedPref;
2182
import org.androidannotations.api.rest.RestClientErrorHandling;
2283
import org.androidannotations.api.rest.RestClientHeaders;
2384
import org.androidannotations.api.rest.RestClientRootUrl;
@@ -27,18 +88,6 @@
2788
import org.androidannotations.model.AnnotationElements;
2889
import org.androidannotations.process.IsValid;
2990

30-
import javax.lang.model.element.*;
31-
import javax.lang.model.type.*;
32-
import javax.lang.model.util.ElementFilter;
33-
import javax.lang.model.util.Elements;
34-
import java.lang.annotation.Annotation;
35-
import java.util.*;
36-
37-
import static java.util.Arrays.asList;
38-
import static org.androidannotations.helper.AndroidConstants.*;
39-
import static org.androidannotations.helper.CanonicalNameConstants.*;
40-
import static org.androidannotations.helper.ModelConstants.*;
41-
4291
public class ValidatorHelper {
4392

4493
private static final List<String> VALID_REST_INTERFACES = asList(RestClientHeaders.class.getName(), RestClientErrorHandling.class.getName(), RestClientRootUrl.class.getName(), RestClientSupport.class.getName());
@@ -383,6 +432,21 @@ public void returnTypeIsVoid(ExecutableElement executableElement, IsValid valid)
383432
}
384433
}
385434

435+
public void doesNotHaveTraceAnnotationAndReturnValue(ExecutableElement executableElement, AnnotationElements validatedElements, IsValid valid) {
436+
TypeMirror returnType = executableElement.getReturnType();
437+
438+
if (elementHasAnnotation(Trace.class, executableElement, validatedElements) && returnType.getKind() != TypeKind.VOID) {
439+
annotationHelper.printAnnotationError(executableElement, "@WakeLock annotated methods with a return value are not supported by @Trace");
440+
}
441+
}
442+
443+
public void doesNotUseFlagsWithPartialWakeLock(Element element, AnnotationElements validatedElements, IsValid valid) {
444+
WakeLock annotation = element.getAnnotation(WakeLock.class);
445+
if (annotation.level().equals(Level.PARTIAL_WAKE_LOCK) && annotation.flags().length > 0) {
446+
annotationHelper.printAnnotationWarning(element, "Flags have no effect when combined with a PARTIAL_WAKE_LOCK");
447+
}
448+
}
449+
386450
public void returnTypeIsNotVoid(ExecutableElement executableElement, IsValid valid) {
387451
TypeMirror returnType = executableElement.getReturnType();
388452

@@ -478,11 +542,9 @@ public void extendsListOfView(Element element, IsValid valid) {
478542

479543
TypeMirror viewType = annotationHelper.typeElementFromQualifiedName(CanonicalNameConstants.VIEW).asType();
480544

481-
if (!elementType.toString().equals(CanonicalNameConstants.LIST)
482-
&& elementTypeArguments.size() == 1
483-
&& !annotationHelper.isSubtype(elementTypeArguments.get(0), viewType)) {
545+
if (!elementType.toString().equals(CanonicalNameConstants.LIST) && elementTypeArguments.size() == 1 && !annotationHelper.isSubtype(elementTypeArguments.get(0), viewType)) {
484546
valid.invalidate();
485-
annotationHelper.printAnnotationError(element, "%s can only be used on a "+CanonicalNameConstants.LIST+ " of elements extending " + CanonicalNameConstants.VIEW);
547+
annotationHelper.printAnnotationError(element, "%s can only be used on a " + CanonicalNameConstants.LIST + " of elements extending " + CanonicalNameConstants.VIEW);
486548
}
487549
}
488550

@@ -1112,16 +1174,22 @@ public void isDebuggable(Element element, AndroidManifest androidManifest, IsVal
11121174
}
11131175

11141176
public void hasInternetPermission(Element element, AndroidManifest androidManifest, IsValid valid) {
1115-
if (androidManifest.isLibraryProject()) {
1116-
return;
1117-
}
1177+
hasPermission(element, androidManifest, valid, INTERNET_PERMISSION);
1178+
}
11181179

1119-
String internetPermissionQualifiedName = INTERNET_PERMISSION;
1180+
public void hasWakeLockPermission(Element element, AndroidManifest androidManifest, IsValid valid) {
1181+
hasPermission(element, androidManifest, valid, WAKELOCK_PERMISSION);
1182+
}
11201183

1184+
public void hasPermission(Element element, AndroidManifest androidManifest, IsValid valid, String permissionQualifiedName) {
11211185
List<String> permissionQualifiedNames = androidManifest.getPermissionQualifiedNames();
1122-
if (!permissionQualifiedNames.contains(internetPermissionQualifiedName)) {
1123-
valid.invalidate();
1124-
annotationHelper.printAnnotationError(element, "Your application must require the INTERNET permission.");
1186+
if (!permissionQualifiedNames.contains(permissionQualifiedName)) {
1187+
if (androidManifest.isLibraryProject()) {
1188+
annotationHelper.printAnnotationWarning(element, "Your library should require the " + permissionQualifiedName + " permission.");
1189+
} else {
1190+
valid.invalidate();
1191+
annotationHelper.printAnnotationError(element, "Your application must require the " + permissionQualifiedName + " permission.");
1192+
}
11251193
}
11261194
}
11271195

0 commit comments

Comments
 (0)