• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package com.android.launcher3.states;
17 
18 import android.content.Intent;
19 import android.os.Binder;
20 import android.os.Bundle;
21 import android.os.IBinder;
22 
23 import com.android.launcher3.Launcher;
24 import com.android.launcher3.LauncherAppState;
25 import com.android.launcher3.LauncherModel.Callbacks;
26 import com.android.launcher3.MainThreadExecutor;
27 
28 import java.lang.ref.WeakReference;
29 
30 /**
31  * Utility class to sending state handling logic to Launcher from within the same process.
32  *
33  * Extending {@link Binder} ensures that the platform maintains a single instance of each object
34  * which allows this object to safely navigate the system process.
35  */
36 public abstract class InternalStateHandler extends Binder {
37 
38     public static final String EXTRA_STATE_HANDLER = "launcher.state_handler";
39 
40     private static final Scheduler sScheduler = new Scheduler();
41 
42     /**
43      * Initializes the handler when the launcher is ready.
44      * @return true if the handler wants to stay alive.
45      */
init(Launcher launcher, boolean alreadyOnHome)46     protected abstract boolean init(Launcher launcher, boolean alreadyOnHome);
47 
addToIntent(Intent intent)48     public final Intent addToIntent(Intent intent) {
49         Bundle extras = new Bundle();
50         extras.putBinder(EXTRA_STATE_HANDLER, this);
51         intent.putExtras(extras);
52         return intent;
53     }
54 
initWhenReady()55     public final void initWhenReady() {
56         sScheduler.schedule(this);
57     }
58 
clearReference()59     public boolean clearReference() {
60         return sScheduler.clearReference(this);
61     }
62 
hasPending()63     public static boolean hasPending() {
64         return sScheduler.hasPending();
65     }
66 
handleCreate(Launcher launcher, Intent intent)67     public static boolean handleCreate(Launcher launcher, Intent intent) {
68         return handleIntent(launcher, intent, false, false);
69     }
70 
handleNewIntent(Launcher launcher, Intent intent, boolean alreadyOnHome)71     public static boolean handleNewIntent(Launcher launcher, Intent intent, boolean alreadyOnHome) {
72         return handleIntent(launcher, intent, alreadyOnHome, true);
73     }
74 
handleIntent( Launcher launcher, Intent intent, boolean alreadyOnHome, boolean explicitIntent)75     private static boolean handleIntent(
76             Launcher launcher, Intent intent, boolean alreadyOnHome, boolean explicitIntent) {
77         boolean result = false;
78         if (intent != null && intent.getExtras() != null) {
79             IBinder stateBinder = intent.getExtras().getBinder(EXTRA_STATE_HANDLER);
80             if (stateBinder instanceof InternalStateHandler) {
81                 InternalStateHandler handler = (InternalStateHandler) stateBinder;
82                 if (!handler.init(launcher, alreadyOnHome)) {
83                     intent.getExtras().remove(EXTRA_STATE_HANDLER);
84                 }
85                 result = true;
86             }
87         }
88         if (!result && !explicitIntent) {
89             result = sScheduler.initIfPending(launcher, alreadyOnHome);
90         }
91         return result;
92     }
93 
94     private static class Scheduler implements Runnable {
95 
96         private WeakReference<InternalStateHandler> mPendingHandler = new WeakReference<>(null);
97         private MainThreadExecutor mMainThreadExecutor;
98 
schedule(InternalStateHandler handler)99         public synchronized void schedule(InternalStateHandler handler) {
100             mPendingHandler = new WeakReference<>(handler);
101             if (mMainThreadExecutor == null) {
102                 mMainThreadExecutor = new MainThreadExecutor();
103             }
104             mMainThreadExecutor.execute(this);
105         }
106 
107         @Override
run()108         public void run() {
109             LauncherAppState app = LauncherAppState.getInstanceNoCreate();
110             if (app == null) {
111                 return;
112             }
113             Callbacks cb = app.getModel().getCallback();
114             if (!(cb instanceof Launcher)) {
115                 return;
116             }
117             Launcher launcher = (Launcher) cb;
118             initIfPending(launcher, launcher.isStarted());
119         }
120 
initIfPending(Launcher launcher, boolean alreadyOnHome)121         public synchronized boolean initIfPending(Launcher launcher, boolean alreadyOnHome) {
122             InternalStateHandler pendingHandler = mPendingHandler.get();
123             if (pendingHandler != null) {
124                 if (!pendingHandler.init(launcher, alreadyOnHome)) {
125                     mPendingHandler.clear();
126                 }
127                 return true;
128             }
129             return false;
130         }
131 
clearReference(InternalStateHandler handler)132         public synchronized boolean clearReference(InternalStateHandler handler) {
133             if (mPendingHandler.get() == handler) {
134                 mPendingHandler.clear();
135                 return true;
136             }
137             return false;
138         }
139 
hasPending()140         public boolean hasPending() {
141             return mPendingHandler.get() != null;
142         }
143     }
144 }