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 
17 package android.appwidget.cts;
18 
19 import android.appwidget.AppWidgetProviderInfo;
20 import android.appwidget.AppWidgetManager;
21 import android.appwidget.AppWidgetHost;
22 import android.appwidget.cts.provider.FirstAppWidgetProvider;
23 import android.appwidget.cts.provider.SecondAppWidgetProvider;
24 import android.os.Bundle;
25 import android.test.suitebuilder.annotation.MediumTest;
26 import android.util.Log;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.os.ParcelFileDescriptor;
30 import android.os.Process;
31 import android.test.InstrumentationTestCase;
32 import java.io.BufferedReader;
33 import java.io.InputStreamReader;
34 import java.util.ArrayList;
35 import java.util.List;
36 
37 @MediumTest
38 public class AppWidgetTest extends InstrumentationTestCase {
39 
40     private static final String TAG = "AppWidgetTest";
41     private static final int HOST_ID = 1001;
42     private static final String GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND =
43         "appwidget grantbind --package android.appwidget.cts --user 0";
44 
45     private Context mContext;
46 
47     @Override
setUp()48     public void setUp() throws Exception {
49         mContext = getInstrumentation().getTargetContext();
50         // Workaround for dexmaker bug: https://code.google.com/p/dexmaker/issues/detail?id=2
51         // Dexmaker is used by mockito.
52         System.setProperty("dexmaker.dexcache", mContext.getCacheDir().getPath());
53     }
54 
testBindWidget1()55     public void testBindWidget1() throws Exception {
56         Log.d(TAG, "binding widget 1 ...");
57         setupWidget(getFirstAppWidgetProviderInfo(), null, true);
58         Log.d(TAG, "binding widget 1 done");
59     }
60 
testBindWidget2()61     public void testBindWidget2() throws Exception {
62         Log.d(TAG, "binding widget 2 ...");
63         Bundle options = new Bundle();
64         options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 1);
65         options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 2);
66         options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 3);
67         options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 4);
68         setupWidget(getSecondAppWidgetProviderInfo(), options, true);
69         Log.d(TAG, "binding widget 2 done");
70     }
71 
testAllocateOnlyWidget1()72     public void testAllocateOnlyWidget1() throws Exception {
73         Log.d(TAG, "allocating widget 1 ...");
74         setupWidget(getFirstAppWidgetProviderInfo(), null, false);
75         Log.d(TAG, "allocating widget 1 done");
76     }
77 
testCleanup()78     public void testCleanup() throws Exception {
79         Log.d(TAG, "deleting host");
80         grantBindAppWidgetPermission();
81         AppWidgetHost host = new AppWidgetHost(mContext, HOST_ID);
82         host.deleteHost();
83     }
84 
setupWidget(AppWidgetProviderInfo prov, Bundle options, boolean bindWidget)85     private void setupWidget(AppWidgetProviderInfo prov, Bundle options, boolean bindWidget) throws Exception {
86         // We want to bind widgets.
87         grantBindAppWidgetPermission();
88 
89         // Create a host and start listening.
90         AppWidgetHost host = new AppWidgetHost(mContext, HOST_ID);
91         host.deleteHost();
92         host.startListening();
93 
94         AppWidgetManager mgr = getAppWidgetManager();
95 
96         // Initially we have no widgets.
97         assertEquals(0, mgr.getAppWidgetIds(prov.provider).length);
98 
99         // Allocate the first widget id to bind.
100         int appWidgetId = host.allocateAppWidgetId();
101 
102         if (bindWidget) {
103             // Bind the widget.
104             getAppWidgetManager().bindAppWidgetIdIfAllowed(appWidgetId,
105                 prov.getProfile(), prov.provider, options);
106 
107             assertEquals(1, mgr.getAppWidgetIds(prov.provider).length);
108         }
109     }
110 
getFirstWidgetComponent()111     private ComponentName getFirstWidgetComponent() {
112         return new ComponentName(mContext.getPackageName(),
113                 FirstAppWidgetProvider.class.getName());
114     }
115 
getSecondWidgetComponent()116     private ComponentName getSecondWidgetComponent() {
117         return new ComponentName(mContext.getPackageName(),
118                 SecondAppWidgetProvider.class.getName());
119     }
120 
runShellCommand(String command)121     private ArrayList<String> runShellCommand(String command) throws Exception {
122         ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
123                 .executeShellCommand(command);
124 
125         ArrayList<String> ret = new ArrayList<>();
126         // Read the input stream fully.
127         try (BufferedReader r = new BufferedReader(
128                 new InputStreamReader(new ParcelFileDescriptor.AutoCloseInputStream(pfd)))) {
129             String line;
130             while ((line = r.readLine()) != null) {
131                 ret.add(line);
132             }
133         }
134         return ret;
135     }
136 
getFirstAppWidgetProviderInfo()137     private AppWidgetProviderInfo getFirstAppWidgetProviderInfo() {
138         return getProviderInfo(getFirstWidgetComponent());
139     }
140 
getSecondAppWidgetProviderInfo()141     private AppWidgetProviderInfo getSecondAppWidgetProviderInfo() {
142         return getProviderInfo(getSecondWidgetComponent());
143     }
144 
getProviderInfo(ComponentName componentName)145     private AppWidgetProviderInfo getProviderInfo(ComponentName componentName) {
146         List<AppWidgetProviderInfo> providers = getAppWidgetManager().getInstalledProviders();
147 
148         final int providerCount = providers.size();
149         for (int i = 0; i < providerCount; i++) {
150             AppWidgetProviderInfo provider = providers.get(i);
151             if (componentName.equals(provider.provider)
152                 && Process.myUserHandle().equals(provider.getProfile())) {
153                 return provider;
154 
155             }
156         }
157 
158         return null;
159     }
160 
getAppWidgetManager()161     private AppWidgetManager getAppWidgetManager() {
162         return (AppWidgetManager) getInstrumentation().getTargetContext()
163             .getSystemService(Context.APPWIDGET_SERVICE);
164     }
165 
grantBindAppWidgetPermission()166     private void grantBindAppWidgetPermission() throws Exception {
167         runShellCommand(GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND);
168     }
169 
170 }
171