• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.systemui.keyguard;
18 
19 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
21 import static android.view.RemoteAnimationTarget.MODE_OPENING;
22 import static android.view.WindowManager.TRANSIT_CLOSE;
23 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
24 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
25 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
26 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
27 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
28 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
29 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
30 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE;
31 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM;
32 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
33 import static android.view.WindowManager.TRANSIT_OLD_NONE;
34 import static android.view.WindowManager.TRANSIT_OPEN;
35 import static android.view.WindowManager.TRANSIT_TO_BACK;
36 import static android.view.WindowManager.TRANSIT_TO_FRONT;
37 import static android.view.WindowManager.TransitionFlags;
38 import static android.view.WindowManager.TransitionOldType;
39 import static android.view.WindowManager.TransitionType;
40 import static android.window.TransitionInfo.FLAG_OCCLUDES_KEYGUARD;
41 
42 import android.app.ActivityManager;
43 import android.app.ActivityTaskManager;
44 import android.app.Service;
45 import android.app.WindowConfiguration;
46 import android.content.Intent;
47 import android.graphics.Point;
48 import android.graphics.Rect;
49 import android.os.Binder;
50 import android.os.Bundle;
51 import android.os.Debug;
52 import android.os.IBinder;
53 import android.os.PowerManager;
54 import android.os.Process;
55 import android.os.RemoteException;
56 import android.os.SystemProperties;
57 import android.os.Trace;
58 import android.util.ArrayMap;
59 import android.util.Log;
60 import android.util.Slog;
61 import android.view.IRemoteAnimationFinishedCallback;
62 import android.view.IRemoteAnimationRunner;
63 import android.view.RemoteAnimationAdapter;
64 import android.view.RemoteAnimationDefinition;
65 import android.view.RemoteAnimationTarget;
66 import android.view.SurfaceControl;
67 import android.view.WindowManager;
68 import android.view.WindowManagerPolicyConstants;
69 import android.window.IRemoteTransition;
70 import android.window.IRemoteTransitionFinishedCallback;
71 import android.window.RemoteTransition;
72 import android.window.TransitionFilter;
73 import android.window.TransitionInfo;
74 
75 import com.android.internal.policy.IKeyguardDismissCallback;
76 import com.android.internal.policy.IKeyguardDrawnCallback;
77 import com.android.internal.policy.IKeyguardExitCallback;
78 import com.android.internal.policy.IKeyguardService;
79 import com.android.internal.policy.IKeyguardStateCallback;
80 import com.android.keyguard.mediator.ScreenOnCoordinator;
81 import com.android.systemui.SystemUIApplication;
82 import com.android.systemui.settings.DisplayTracker;
83 import com.android.wm.shell.transition.ShellTransitions;
84 import com.android.wm.shell.transition.Transitions;
85 
86 import java.util.ArrayList;
87 
88 import javax.inject.Inject;
89 
90 public class KeyguardService extends Service {
91     static final String TAG = "KeyguardService";
92     static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
93 
94     /**
95      * Run Keyguard animation as remote animation in System UI instead of local animation in
96      * the server process.
97      *
98      * 0: Runs all keyguard animation as local animation
99      * 1: Only runs keyguard going away animation as remote animation
100      * 2: Runs all keyguard animation as remote animation
101      *
102      * Note: Must be consistent with WindowManagerService.
103      */
104     private static final String ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY =
105             "persist.wm.enable_remote_keyguard_animation";
106 
107     private static final int sEnableRemoteKeyguardAnimation =
108             SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 2);
109 
110     /**
111      * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
112      */
113     public static boolean sEnableRemoteKeyguardGoingAwayAnimation =
114             sEnableRemoteKeyguardAnimation >= 1;
115 
116     /**
117      * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
118      */
119     public static boolean sEnableRemoteKeyguardOccludeAnimation =
120             sEnableRemoteKeyguardAnimation >= 2;
121 
122     private final KeyguardViewMediator mKeyguardViewMediator;
123     private final KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
124     private final ScreenOnCoordinator mScreenOnCoordinator;
125     private final ShellTransitions mShellTransitions;
126     private final DisplayTracker mDisplayTracker;
127 
newModeToLegacyMode(int newMode)128     private static int newModeToLegacyMode(int newMode) {
129         switch (newMode) {
130             case WindowManager.TRANSIT_OPEN:
131             case WindowManager.TRANSIT_TO_FRONT:
132                 return MODE_OPENING;
133             case WindowManager.TRANSIT_CLOSE:
134             case WindowManager.TRANSIT_TO_BACK:
135                 return MODE_CLOSING;
136             default:
137                 return 2; // MODE_CHANGING
138         }
139     }
140 
wrap(TransitionInfo info, boolean wallpapers)141     private static RemoteAnimationTarget[] wrap(TransitionInfo info, boolean wallpapers) {
142         final ArrayList<RemoteAnimationTarget> out = new ArrayList<>();
143         for (int i = 0; i < info.getChanges().size(); i++) {
144             boolean changeIsWallpaper =
145                     (info.getChanges().get(i).getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0;
146             if (wallpapers != changeIsWallpaper) continue;
147 
148             final TransitionInfo.Change change = info.getChanges().get(i);
149             final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
150             final int taskId = taskInfo != null ? change.getTaskInfo().taskId : -1;
151             boolean isNotInRecents;
152             WindowConfiguration windowConfiguration = null;
153             if (taskInfo != null) {
154                 if (taskInfo.getConfiguration() != null) {
155                     windowConfiguration =
156                             change.getTaskInfo().getConfiguration().windowConfiguration;
157                 }
158                 isNotInRecents = !change.getTaskInfo().isRunning;
159             } else {
160                 isNotInRecents = true;
161             }
162             Rect localBounds = new Rect(change.getEndAbsBounds());
163             localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);
164 
165             final RemoteAnimationTarget target = new RemoteAnimationTarget(
166                     taskId,
167                     newModeToLegacyMode(change.getMode()),
168                     change.getLeash(),
169                     (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0
170                             || (change.getFlags() & TransitionInfo.FLAG_SHOW_WALLPAPER) != 0,
171                     null /* clipRect */,
172                     new Rect(0, 0, 0, 0) /* contentInsets */,
173                     info.getChanges().size() - i,
174                     new Point(), localBounds, new Rect(change.getEndAbsBounds()),
175                     windowConfiguration, isNotInRecents, null /* startLeash */,
176                     change.getStartAbsBounds(), taskInfo, false /* allowEnterPip */);
177             // Use hasAnimatingParent to mark the anything below root task
178             if (taskId != -1 && change.getParent() != null) {
179                 final TransitionInfo.Change parentChange = info.getChange(change.getParent());
180                 if (parentChange != null && parentChange.getTaskInfo() != null) {
181                     target.hasAnimatingParent = true;
182                 }
183             }
184             out.add(target);
185         }
186         return out.toArray(new RemoteAnimationTarget[out.size()]);
187     }
188 
getTransitionOldType(@ransitionType int type, @TransitionFlags int flags, RemoteAnimationTarget[] apps)189     private static @TransitionOldType int getTransitionOldType(@TransitionType int type,
190             @TransitionFlags int flags, RemoteAnimationTarget[] apps) {
191         if (type == TRANSIT_KEYGUARD_GOING_AWAY
192                 || (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) {
193             return apps.length == 0 ? TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER
194                     : TRANSIT_OLD_KEYGUARD_GOING_AWAY;
195         } else if (type == TRANSIT_KEYGUARD_OCCLUDE) {
196             boolean isOccludeByDream = apps.length > 0 && apps[0].taskInfo.topActivityType
197                     == WindowConfiguration.ACTIVITY_TYPE_DREAM;
198             if (isOccludeByDream) return TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM;
199             return TRANSIT_OLD_KEYGUARD_OCCLUDE;
200         } else if (type == TRANSIT_KEYGUARD_UNOCCLUDE) {
201             return TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
202         } else {
203             Slog.d(TAG, "Unexpected transit type: " + type);
204             return TRANSIT_OLD_NONE;
205         }
206     }
207 
208     // Wrap Keyguard going away animation.
209     // Note: Also used for wrapping occlude by Dream animation. It works (with some redundancy).
wrap(IRemoteAnimationRunner runner)210     private static IRemoteTransition wrap(IRemoteAnimationRunner runner) {
211         return new IRemoteTransition.Stub() {
212             final ArrayMap<IBinder, IRemoteTransitionFinishedCallback> mFinishCallbacks =
213                     new ArrayMap<>();
214 
215             @Override
216             public void startAnimation(IBinder transition, TransitionInfo info,
217                     SurfaceControl.Transaction t, IRemoteTransitionFinishedCallback finishCallback)
218                     throws RemoteException {
219                 Slog.d(TAG, "Starts IRemoteAnimationRunner: info=" + info);
220                 final RemoteAnimationTarget[] apps = wrap(info, false /* wallpapers */);
221                 final RemoteAnimationTarget[] wallpapers = wrap(info, true /* wallpapers */);
222                 final RemoteAnimationTarget[] nonApps = new RemoteAnimationTarget[0];
223 
224                 // Sets the alpha to 0 for the opening root task for fade in animation. And since
225                 // the fade in animation can only apply on the first opening app, so set alpha to 1
226                 // for anything else.
227                 boolean foundOpening = false;
228                 for (RemoteAnimationTarget target : apps) {
229                     if (target.taskId != -1
230                             && target.mode == RemoteAnimationTarget.MODE_OPENING
231                             && !target.hasAnimatingParent) {
232                         if (foundOpening) {
233                             Log.w(TAG, "More than one opening target");
234                             t.setAlpha(target.leash, 1.0f);
235                             continue;
236                         }
237                         t.setAlpha(target.leash, 0.0f);
238                         foundOpening = true;
239                     } else {
240                         t.setAlpha(target.leash, 1.0f);
241                     }
242                 }
243                 t.apply();
244                 synchronized (mFinishCallbacks) {
245                     mFinishCallbacks.put(transition, finishCallback);
246                 }
247                 runner.onAnimationStart(getTransitionOldType(info.getType(), info.getFlags(), apps),
248                         apps, wallpapers, nonApps,
249                         new IRemoteAnimationFinishedCallback.Stub() {
250                             @Override
251                             public void onAnimationFinished() throws RemoteException {
252                                 synchronized (mFinishCallbacks) {
253                                     if (mFinishCallbacks.remove(transition) == null) return;
254                                 }
255                                 info.releaseAllSurfaces();
256                                 Slog.d(TAG, "Finish IRemoteAnimationRunner.");
257                                 finishCallback.onTransitionFinished(null /* wct */, null /* t */);
258                             }
259                         }
260                 );
261             }
262 
263             public void mergeAnimation(IBinder candidateTransition, TransitionInfo candidateInfo,
264                     SurfaceControl.Transaction candidateT, IBinder currentTransition,
265                     IRemoteTransitionFinishedCallback candidateFinishCallback) {
266                 try {
267                     final IRemoteTransitionFinishedCallback currentFinishCB;
268                     synchronized (mFinishCallbacks) {
269                         currentFinishCB = mFinishCallbacks.remove(currentTransition);
270                     }
271                     if (currentFinishCB == null) {
272                         Slog.e(TAG, "Called mergeAnimation, but finish callback is missing");
273                         return;
274                     }
275                     runner.onAnimationCancelled(false /* isKeyguardOccluded */);
276                     currentFinishCB.onTransitionFinished(null /* wct */, null /* t */);
277                 } catch (RemoteException e) {
278                     // nothing, we'll just let it finish on its own I guess.
279                 }
280             }
281         };
282     }
283 
284     @Inject
KeyguardService(KeyguardViewMediator keyguardViewMediator, KeyguardLifecyclesDispatcher keyguardLifecyclesDispatcher, ScreenOnCoordinator screenOnCoordinator, ShellTransitions shellTransitions, DisplayTracker displayTracker)285     public KeyguardService(KeyguardViewMediator keyguardViewMediator,
286                            KeyguardLifecyclesDispatcher keyguardLifecyclesDispatcher,
287                            ScreenOnCoordinator screenOnCoordinator,
288                            ShellTransitions shellTransitions,
289                            DisplayTracker displayTracker) {
290         super();
291         mKeyguardViewMediator = keyguardViewMediator;
292         mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
293         mScreenOnCoordinator = screenOnCoordinator;
294         mShellTransitions = shellTransitions;
295         mDisplayTracker = displayTracker;
296     }
297 
298     @Override
onCreate()299     public void onCreate() {
300         ((SystemUIApplication) getApplication()).startServicesIfNeeded();
301 
302         if (mShellTransitions == null || !Transitions.ENABLE_SHELL_TRANSITIONS) {
303             RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
304             if (sEnableRemoteKeyguardGoingAwayAnimation) {
305                 final RemoteAnimationAdapter exitAnimationAdapter =
306                         new RemoteAnimationAdapter(mExitAnimationRunner, 0, 0);
307                 definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY,
308                         exitAnimationAdapter);
309                 definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
310                         exitAnimationAdapter);
311             }
312             if (sEnableRemoteKeyguardOccludeAnimation) {
313                 final RemoteAnimationAdapter occludeAnimationAdapter =
314                         new RemoteAnimationAdapter(
315                                 mKeyguardViewMediator.getOccludeAnimationRunner(), 0, 0);
316                 definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_OCCLUDE,
317                         occludeAnimationAdapter);
318 
319                 final RemoteAnimationAdapter occludeByDreamAnimationAdapter =
320                         new RemoteAnimationAdapter(
321                                 mKeyguardViewMediator.getOccludeByDreamAnimationRunner(), 0, 0);
322                 definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM,
323                         occludeByDreamAnimationAdapter);
324 
325                 final RemoteAnimationAdapter unoccludeAnimationAdapter =
326                         new RemoteAnimationAdapter(
327                                 mKeyguardViewMediator.getUnoccludeAnimationRunner(), 0, 0);
328                 definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_UNOCCLUDE,
329                         unoccludeAnimationAdapter);
330             }
331             ActivityTaskManager.getInstance().registerRemoteAnimationsForDisplay(
332                     mDisplayTracker.getDefaultDisplayId(), definition);
333             return;
334         }
335         if (sEnableRemoteKeyguardGoingAwayAnimation) {
336             Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_GOING_AWAY");
337             TransitionFilter f = new TransitionFilter();
338             f.mFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
339             mShellTransitions.registerRemote(f,
340                     new RemoteTransition(wrap(mExitAnimationRunner), getIApplicationThread()));
341         }
342         if (sEnableRemoteKeyguardOccludeAnimation) {
343             Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_(UN)OCCLUDE");
344             // Register for occluding
345             final RemoteTransition occludeTransition = new RemoteTransition(
346                     mOccludeAnimation, getIApplicationThread());
347             TransitionFilter f = new TransitionFilter();
348             f.mFlags = TRANSIT_FLAG_KEYGUARD_LOCKED;
349             f.mRequirements = new TransitionFilter.Requirement[]{
350                     new TransitionFilter.Requirement(), new TransitionFilter.Requirement()};
351             // First require at-least one app showing that occludes.
352             f.mRequirements[0].mMustBeIndependent = false;
353             f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD;
354             f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
355             // Then require that we aren't closing any occludes (because this would mean a
356             // regular task->task or activity->activity animation not involving keyguard).
357             f.mRequirements[1].mNot = true;
358             f.mRequirements[1].mMustBeIndependent = false;
359             f.mRequirements[1].mFlags = FLAG_OCCLUDES_KEYGUARD;
360             f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
361             mShellTransitions.registerRemote(f, occludeTransition);
362 
363             // Now register for un-occlude.
364             final RemoteTransition unoccludeTransition = new RemoteTransition(
365                     mUnoccludeAnimation, getIApplicationThread());
366             f = new TransitionFilter();
367             f.mFlags = TRANSIT_FLAG_KEYGUARD_LOCKED;
368             f.mRequirements = new TransitionFilter.Requirement[]{
369                     new TransitionFilter.Requirement(), new TransitionFilter.Requirement()};
370             // First require at-least one app going-away (doesn't need occlude flag
371             // as that is implicit by it having been visible and we don't want to exclude
372             // cases where we are un-occluding because the app removed its showWhenLocked
373             // capability at runtime).
374             f.mRequirements[1].mMustBeIndependent = false;
375             f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
376             f.mRequirements[1].mMustBeTask = true;
377             // Then require that we aren't opening any occludes (otherwise we'd remain
378             // occluded).
379             f.mRequirements[0].mNot = true;
380             f.mRequirements[0].mMustBeIndependent = false;
381             f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD;
382             f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
383             mShellTransitions.registerRemote(f, unoccludeTransition);
384 
385             // Register for specific transition type.
386             // Above filter cannot fulfill all conditions.
387             // E.g. close top activity while screen off but next activity is occluded, this should
388             // an occluded transition, but since the activity is invisible, the condition would
389             // match unoccluded transition.
390             // But on the contrary, if we add above condition in occluded transition, then when user
391             // trying to dismiss occluded activity when unlock keyguard, the condition would match
392             // occluded transition.
393             f = new TransitionFilter();
394             f.mTypeSet = new int[]{TRANSIT_KEYGUARD_OCCLUDE};
395             mShellTransitions.registerRemote(f, occludeTransition);
396 
397             f = new TransitionFilter();
398             f.mTypeSet = new int[]{TRANSIT_KEYGUARD_UNOCCLUDE};
399             mShellTransitions.registerRemote(f, unoccludeTransition);
400 
401             Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_OCCLUDE for DREAM");
402             // Register for occluding by Dream
403             f = new TransitionFilter();
404             f.mFlags = TRANSIT_FLAG_KEYGUARD_LOCKED;
405             f.mRequirements = new TransitionFilter.Requirement[]{
406                     new TransitionFilter.Requirement(), new TransitionFilter.Requirement()};
407             // First require at-least one app of type DREAM showing that occludes.
408             f.mRequirements[0].mActivityType = WindowConfiguration.ACTIVITY_TYPE_DREAM;
409             f.mRequirements[0].mMustBeIndependent = false;
410             f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD;
411             f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
412             // Then require that we aren't closing any occludes (because this would mean a
413             // regular task->task or activity->activity animation not involving keyguard).
414             f.mRequirements[1].mNot = true;
415             f.mRequirements[1].mMustBeIndependent = false;
416             f.mRequirements[1].mFlags = FLAG_OCCLUDES_KEYGUARD;
417             f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
418             mShellTransitions.registerRemote(f, new RemoteTransition(
419                     wrap(mKeyguardViewMediator.getOccludeByDreamAnimationRunner()),
420                     getIApplicationThread()));
421         }
422     }
423 
424     @Override
onBind(Intent intent)425     public IBinder onBind(Intent intent) {
426         return mBinder;
427     }
428 
checkPermission()429     void checkPermission() {
430         // Avoid deadlock by avoiding calling back into the system process.
431         if (Binder.getCallingUid() == Process.SYSTEM_UID) return;
432 
433         // Otherwise,explicitly check for caller permission ...
434         if (getBaseContext().checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
435             Log.w(TAG, "Caller needs permission '" + PERMISSION + "' to call " + Debug.getCaller());
436             throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
437                     + ", must have permission " + PERMISSION);
438         }
439     }
440 
441     private final IRemoteAnimationRunner.Stub mExitAnimationRunner =
442             new IRemoteAnimationRunner.Stub() {
443         @Override // Binder interface
444         public void onAnimationStart(@WindowManager.TransitionOldType int transit,
445                 RemoteAnimationTarget[] apps,
446                 RemoteAnimationTarget[] wallpapers,
447                 RemoteAnimationTarget[] nonApps,
448                 IRemoteAnimationFinishedCallback finishedCallback) {
449             Trace.beginSection("mExitAnimationRunner.onAnimationStart#startKeyguardExitAnimation");
450             checkPermission();
451             mKeyguardViewMediator.startKeyguardExitAnimation(transit, apps, wallpapers,
452                     nonApps, finishedCallback);
453             Trace.endSection();
454         }
455 
456         @Override // Binder interface
457         public void onAnimationCancelled(boolean isKeyguardOccluded) {
458             mKeyguardViewMediator.cancelKeyguardExitAnimation();
459         }
460     };
461 
462     final IRemoteTransition mOccludeAnimation = new IRemoteTransition.Stub() {
463         @Override
464         public void startAnimation(IBinder transition, TransitionInfo info,
465                 SurfaceControl.Transaction t, IRemoteTransitionFinishedCallback finishCallback)
466                     throws RemoteException {
467             t.apply();
468             mBinder.setOccluded(true /* isOccluded */, true /* animate */);
469             finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
470             info.releaseAllSurfaces();
471         }
472 
473         @Override
474         public void mergeAnimation(IBinder transition, TransitionInfo info,
475                 SurfaceControl.Transaction t, IBinder mergeTarget,
476                 IRemoteTransitionFinishedCallback finishCallback) {
477             t.close();
478             info.releaseAllSurfaces();
479         }
480     };
481 
482     final IRemoteTransition mUnoccludeAnimation = new IRemoteTransition.Stub() {
483         @Override
484         public void startAnimation(IBinder transition, TransitionInfo info,
485                 SurfaceControl.Transaction t, IRemoteTransitionFinishedCallback finishCallback)
486                 throws RemoteException {
487             t.apply();
488             mBinder.setOccluded(false /* isOccluded */, true /* animate */);
489             finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
490             info.releaseAllSurfaces();
491         }
492 
493         @Override
494         public void mergeAnimation(IBinder transition, TransitionInfo info,
495                 SurfaceControl.Transaction t, IBinder mergeTarget,
496                 IRemoteTransitionFinishedCallback finishCallback) {
497             t.close();
498             info.releaseAllSurfaces();
499         }
500     };
501 
502     private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
503 
504         @Override // Binder interface
505         public void addStateMonitorCallback(IKeyguardStateCallback callback) {
506             checkPermission();
507             mKeyguardViewMediator.addStateMonitorCallback(callback);
508         }
509 
510         @Override // Binder interface
511         public void verifyUnlock(IKeyguardExitCallback callback) {
512             Trace.beginSection("KeyguardService.mBinder#verifyUnlock");
513             checkPermission();
514             mKeyguardViewMediator.verifyUnlock(callback);
515             Trace.endSection();
516         }
517 
518         @Override // Binder interface
519         public void setOccluded(boolean isOccluded, boolean animate) {
520             Log.d(TAG, "setOccluded(" + isOccluded + ")");
521 
522             Trace.beginSection("KeyguardService.mBinder#setOccluded");
523             checkPermission();
524             mKeyguardViewMediator.setOccluded(isOccluded, animate);
525             Trace.endSection();
526         }
527 
528         @Override // Binder interface
529         public void dismiss(IKeyguardDismissCallback callback, CharSequence message) {
530             checkPermission();
531             mKeyguardViewMediator.dismiss(callback, message);
532         }
533 
534         @Override // Binder interface
535         public void onDreamingStarted() {
536             checkPermission();
537             mKeyguardViewMediator.onDreamingStarted();
538         }
539 
540         @Override // Binder interface
541         public void onDreamingStopped() {
542             checkPermission();
543             mKeyguardViewMediator.onDreamingStopped();
544         }
545 
546         @Override // Binder interface
547         public void onStartedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason) {
548             checkPermission();
549             mKeyguardViewMediator.onStartedGoingToSleep(
550                     WindowManagerPolicyConstants.translateSleepReasonToOffReason(pmSleepReason));
551             mKeyguardLifecyclesDispatcher.dispatch(
552                     KeyguardLifecyclesDispatcher.STARTED_GOING_TO_SLEEP, pmSleepReason);
553         }
554 
555         @Override // Binder interface
556         public void onFinishedGoingToSleep(
557                 @PowerManager.GoToSleepReason int pmSleepReason, boolean cameraGestureTriggered) {
558             checkPermission();
559             mKeyguardViewMediator.onFinishedGoingToSleep(
560                     WindowManagerPolicyConstants.translateSleepReasonToOffReason(pmSleepReason),
561                     cameraGestureTriggered);
562             mKeyguardLifecyclesDispatcher.dispatch(
563                     KeyguardLifecyclesDispatcher.FINISHED_GOING_TO_SLEEP);
564         }
565 
566         @Override // Binder interface
567         public void onStartedWakingUp(
568                 @PowerManager.WakeReason int pmWakeReason, boolean cameraGestureTriggered) {
569             Trace.beginSection("KeyguardService.mBinder#onStartedWakingUp");
570             checkPermission();
571             mKeyguardViewMediator.onStartedWakingUp(pmWakeReason, cameraGestureTriggered);
572             mKeyguardLifecyclesDispatcher.dispatch(
573                     KeyguardLifecyclesDispatcher.STARTED_WAKING_UP, pmWakeReason);
574             Trace.endSection();
575         }
576 
577         @Override // Binder interface
578         public void onFinishedWakingUp() {
579             Trace.beginSection("KeyguardService.mBinder#onFinishedWakingUp");
580             checkPermission();
581             mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.FINISHED_WAKING_UP);
582             Trace.endSection();
583         }
584 
585         @Override // Binder interface
586         public void onScreenTurningOn(IKeyguardDrawnCallback callback) {
587             Trace.beginSection("KeyguardService.mBinder#onScreenTurningOn");
588             checkPermission();
589             mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNING_ON,
590                     callback);
591 
592             final String onDrawWaitingTraceTag = "Waiting for KeyguardDrawnCallback#onDrawn";
593             final int traceCookie = System.identityHashCode(callback);
594             Trace.beginAsyncSection(onDrawWaitingTraceTag, traceCookie);
595 
596             // Ensure the drawn callback is only ever called once
597             mScreenOnCoordinator.onScreenTurningOn(new Runnable() {
598                 boolean mInvoked;
599                 @Override
600                 public void run() {
601                     if (callback == null) return;
602                     if (!mInvoked) {
603                         mInvoked = true;
604                         try {
605                             Trace.endAsyncSection(onDrawWaitingTraceTag, traceCookie);
606                             callback.onDrawn();
607                         } catch (RemoteException e) {
608                             Log.w(TAG, "Exception calling onDrawn():", e);
609                         }
610                     } else {
611                         Log.w(TAG, "KeyguardDrawnCallback#onDrawn() invoked > 1 times");
612                     }
613                 }
614             });
615 
616             Trace.endSection();
617         }
618 
619         @Override // Binder interface
620         public void onScreenTurnedOn() {
621             Trace.beginSection("KeyguardService.mBinder#onScreenTurnedOn");
622             checkPermission();
623             mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNED_ON);
624             mScreenOnCoordinator.onScreenTurnedOn();
625             Trace.endSection();
626         }
627 
628         @Override // Binder interface
629         public void onScreenTurningOff() {
630             checkPermission();
631             mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNING_OFF);
632         }
633 
634         @Override // Binder interface
635         public void onScreenTurnedOff() {
636             checkPermission();
637             mKeyguardViewMediator.onScreenTurnedOff();
638             mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNED_OFF);
639             mScreenOnCoordinator.onScreenTurnedOff();
640         }
641 
642         @Override // Binder interface
643         public void setKeyguardEnabled(boolean enabled) {
644             checkPermission();
645             mKeyguardViewMediator.setKeyguardEnabled(enabled);
646         }
647 
648         @Override // Binder interface
649         public void onSystemReady() {
650             Trace.beginSection("KeyguardService.mBinder#onSystemReady");
651             checkPermission();
652             mKeyguardViewMediator.onSystemReady();
653             Trace.endSection();
654         }
655 
656         @Override // Binder interface
657         public void doKeyguardTimeout(Bundle options) {
658             checkPermission();
659             mKeyguardViewMediator.doKeyguardTimeout(options);
660         }
661 
662         @Override // Binder interface
663         public void setSwitchingUser(boolean switching) {
664             checkPermission();
665             mKeyguardViewMediator.setSwitchingUser(switching);
666         }
667 
668         @Override // Binder interface
669         public void setCurrentUser(int userId) {
670             checkPermission();
671             mKeyguardViewMediator.setCurrentUser(userId);
672         }
673 
674         @Override
675         public void onBootCompleted() {
676             checkPermission();
677             mKeyguardViewMediator.onBootCompleted();
678         }
679 
680         /**
681          * @deprecated When remote animation is enabled, this won't be called anymore. Use
682          * {@code IRemoteAnimationRunner#onAnimationStart} instead.
683          */
684         @Deprecated
685         @Override
686         public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
687             Trace.beginSection("KeyguardService.mBinder#startKeyguardExitAnimation");
688             checkPermission();
689             mKeyguardViewMediator.startKeyguardExitAnimation(startTime, fadeoutDuration);
690             Trace.endSection();
691         }
692 
693         @Override
694         public void onShortPowerPressedGoHome() {
695             checkPermission();
696             mKeyguardViewMediator.onShortPowerPressedGoHome();
697         }
698 
699         @Override
700         public void dismissKeyguardToLaunch(Intent intentToLaunch) {
701             checkPermission();
702             mKeyguardViewMediator.dismissKeyguardToLaunch(intentToLaunch);
703         }
704 
705         @Override
706         public void onSystemKeyPressed(int keycode) {
707             checkPermission();
708             mKeyguardViewMediator.onSystemKeyPressed(keycode);
709         }
710     };
711 }
712 
713