1717package com .android .server ;
1818
1919import android .app .ActivityManagerNative ;
20- import android .app .AlarmManager ;
21- import android .app .PendingIntent ;
22- import android .appwidget .AppWidgetManager ;
2320import android .appwidget .AppWidgetProviderInfo ;
2421import android .content .BroadcastReceiver ;
2522import android .content .ComponentName ;
2623import android .content .Context ;
2724import android .content .Intent ;
2825import android .content .IntentFilter ;
29- import android .content .ServiceConnection ;
3026import android .content .pm .PackageManager ;
3127import android .os .Binder ;
3228import android .os .Bundle ;
3329import android .os .IBinder ;
3430import android .os .RemoteException ;
3531import android .os .UserHandle ;
36- import android .util .Pair ;
3732import android .util .Slog ;
3833import android .util .SparseArray ;
3934import android .widget .RemoteViews ;
4035
4136import com .android .internal .appwidget .IAppWidgetHost ;
4237import com .android .internal .appwidget .IAppWidgetService ;
43- import com .android .internal .widget . IRemoteViewsAdapterConnection ;
38+ import com .android .internal .util . IndentingPrintWriter ;
4439
4540import java .io .FileDescriptor ;
4641import java .io .PrintWriter ;
47- import java .util .ArrayList ;
4842import java .util .List ;
4943import java .util .Locale ;
5044
@@ -56,85 +50,11 @@ class AppWidgetService extends IAppWidgetService.Stub
5650{
5751 private static final String TAG = "AppWidgetService" ;
5852
59- /*
60- * When identifying a Host or Provider based on the calling process, use the uid field.
61- * When identifying a Host or Provider based on a package manager broadcast, use the
62- * package given.
63- */
64-
65- static class Provider {
66- int uid ;
67- AppWidgetProviderInfo info ;
68- ArrayList <AppWidgetId > instances = new ArrayList <AppWidgetId >();
69- PendingIntent broadcast ;
70- boolean zombie ; // if we're in safe mode, don't prune this just because nobody references it
71-
72- int tag ; // for use while saving state (the index)
73- }
74-
75- static class Host {
76- int uid ;
77- int hostId ;
78- String packageName ;
79- ArrayList <AppWidgetId > instances = new ArrayList <AppWidgetId >();
80- IAppWidgetHost callbacks ;
81- boolean zombie ; // if we're in safe mode, don't prune this just because nobody references it
82-
83- int tag ; // for use while saving state (the index)
84- }
85-
86- static class AppWidgetId {
87- int appWidgetId ;
88- Provider provider ;
89- RemoteViews views ;
90- Host host ;
91- }
92-
93- /**
94- * Acts as a proxy between the ServiceConnection and the RemoteViewsAdapterConnection.
95- * This needs to be a static inner class since a reference to the ServiceConnection is held
96- * globally and may lead us to leak AppWidgetService instances (if there were more than one).
97- */
98- static class ServiceConnectionProxy implements ServiceConnection {
99- private final IBinder mConnectionCb ;
100-
101- ServiceConnectionProxy (Pair <Integer , Intent .FilterComparison > key , IBinder connectionCb ) {
102- mConnectionCb = connectionCb ;
103- }
104- public void onServiceConnected (ComponentName name , IBinder service ) {
105- final IRemoteViewsAdapterConnection cb =
106- IRemoteViewsAdapterConnection .Stub .asInterface (mConnectionCb );
107- try {
108- cb .onServiceConnected (service );
109- } catch (Exception e ) {
110- e .printStackTrace ();
111- }
112- }
113- public void onServiceDisconnected (ComponentName name ) {
114- disconnect ();
115- }
116- public void disconnect () {
117- final IRemoteViewsAdapterConnection cb =
118- IRemoteViewsAdapterConnection .Stub .asInterface (mConnectionCb );
119- try {
120- cb .onServiceDisconnected ();
121- } catch (Exception e ) {
122- e .printStackTrace ();
123- }
124- }
125- }
126-
12753 Context mContext ;
12854 Locale mLocale ;
12955 PackageManager mPackageManager ;
130- AlarmManager mAlarmManager ;
131- ArrayList <Provider > mInstalledProviders = new ArrayList <Provider >();
132- int mNextAppWidgetId = AppWidgetManager .INVALID_APPWIDGET_ID + 1 ;
133- final ArrayList <AppWidgetId > mAppWidgetIds = new ArrayList <AppWidgetId >();
134- ArrayList <Host > mHosts = new ArrayList <Host >();
13556 boolean mSafeMode ;
13657
137-
13858 private final SparseArray <AppWidgetServiceImpl > mAppWidgetServices ;
13959
14060 AppWidgetService (Context context ) {
@@ -195,9 +115,16 @@ public void onReceive(Context context, Intent intent) {
195115 }, UserHandle .ALL , userFilter , null , null );
196116 }
197117
118+ /**
119+ * This returns the user id of the caller, if the caller is not the system process,
120+ * otherwise it assumes that the calls are from the lockscreen and hence are meant for the
121+ * current user. TODO: Instead, have lockscreen make explicit calls with userId
122+ */
198123 private int getCallingOrCurrentUserId () {
199124 int callingUid = Binder .getCallingUid ();
200- if (callingUid == android .os .Process .myUid ()) {
125+ // Also check the PID because Settings (power control widget) also runs as System UID
126+ if (callingUid == android .os .Process .myUid ()
127+ && Binder .getCallingPid () == android .os .Process .myPid ()) {
201128 try {
202129 return ActivityManagerNative .getDefault ().getCurrentUser ().id ;
203130 } catch (RemoteException re ) {
@@ -272,31 +199,40 @@ public int[] startListening(IAppWidgetHost host, String packageName, int hostId,
272199 }
273200
274201 public void onUserRemoved (int userId ) {
275- AppWidgetServiceImpl impl = mAppWidgetServices .get (userId );
276202 if (userId < 1 ) return ;
277-
278- if (impl == null ) {
279- AppWidgetServiceImpl .getSettingsFile (userId ).delete ();
280- } else {
281- impl .onUserRemoved ();
203+ synchronized (mAppWidgetServices ) {
204+ AppWidgetServiceImpl impl = mAppWidgetServices .get (userId );
205+ mAppWidgetServices .remove (userId );
206+
207+ if (impl == null ) {
208+ AppWidgetServiceImpl .getSettingsFile (userId ).delete ();
209+ } else {
210+ impl .onUserRemoved ();
211+ }
282212 }
283213 }
284214
285215 public void onUserStopped (int userId ) {
286216 }
287217
288218 private AppWidgetServiceImpl getImplForUser (int userId ) {
289- AppWidgetServiceImpl service = mAppWidgetServices .get (userId );
290- if (service == null ) {
291- Slog .e (TAG , "Unable to find AppWidgetServiceImpl for the current user" );
292- // TODO: Verify that it's a valid user
293- service = new AppWidgetServiceImpl (mContext , userId );
294- service .systemReady (mSafeMode );
295- // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
219+ boolean sendInitial = false ;
220+ AppWidgetServiceImpl service ;
221+ synchronized (mAppWidgetServices ) {
222+ service = mAppWidgetServices .get (userId );
223+ if (service == null ) {
224+ Slog .i (TAG , "Unable to find AppWidgetServiceImpl for user " + userId + ", adding" );
225+ // TODO: Verify that it's a valid user
226+ service = new AppWidgetServiceImpl (mContext , userId );
227+ service .systemReady (mSafeMode );
228+ // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
229+ mAppWidgetServices .append (userId , service );
230+ sendInitial = true ;
231+ }
232+ }
233+ if (sendInitial ) {
296234 service .sendInitialBroadcasts ();
297- mAppWidgetServices .append (userId , service );
298235 }
299-
300236 return service ;
301237 }
302238
@@ -325,15 +261,6 @@ public Bundle getAppWidgetOptions(int appWidgetId) {
325261 return getImplForUser (getCallingOrCurrentUserId ()).getAppWidgetOptions (appWidgetId );
326262 }
327263
328- static int [] getAppWidgetIds (Provider p ) {
329- int instancesSize = p .instances .size ();
330- int appWidgetIds [] = new int [instancesSize ];
331- for (int i =0 ; i <instancesSize ; i ++) {
332- appWidgetIds [i ] = p .instances .get (i ).appWidgetId ;
333- }
334- return appWidgetIds ;
335- }
336-
337264 @ Override
338265 public List <AppWidgetProviderInfo > getInstalledProviders () throws RemoteException {
339266 return getImplForUser (getCallingOrCurrentUserId ()).getInstalledProviders ();
@@ -378,9 +305,15 @@ public void updateAppWidgetProvider(ComponentName provider, RemoteViews views)
378305 @ Override
379306 public void dump (FileDescriptor fd , PrintWriter pw , String [] args ) {
380307 // Dump the state of all the app widget providers
381- for (int i = 0 ; i < mAppWidgetServices .size (); i ++) {
382- AppWidgetServiceImpl service = mAppWidgetServices .valueAt (i );
383- service .dump (fd , pw , args );
308+ synchronized (mAppWidgetServices ) {
309+ IndentingPrintWriter ipw = new IndentingPrintWriter (pw , " " );
310+ for (int i = 0 ; i < mAppWidgetServices .size (); i ++) {
311+ pw .println ("User: " + mAppWidgetServices .keyAt (i ));
312+ ipw .increaseIndent ();
313+ AppWidgetServiceImpl service = mAppWidgetServices .valueAt (i );
314+ service .dump (fd , ipw , args );
315+ ipw .decreaseIndent ();
316+ }
384317 }
385318 }
386319
0 commit comments