• 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 
17 package com.android.launcher3.util;
18 
19 import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_HOME_ROLE;
20 
21 import android.app.ActivityOptions;
22 import android.app.Person;
23 import android.app.role.RoleManager;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.ApplicationInfo;
27 import android.content.pm.LauncherActivityInfo;
28 import android.content.pm.ShortcutInfo;
29 import android.graphics.drawable.ColorDrawable;
30 import android.net.Uri;
31 import android.os.Process;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.util.ArrayMap;
35 
36 import androidx.annotation.NonNull;
37 import androidx.annotation.Nullable;
38 
39 import com.android.launcher3.BuildConfig;
40 import com.android.launcher3.Launcher;
41 import com.android.launcher3.Utilities;
42 import com.android.launcher3.dagger.ApplicationContext;
43 import com.android.launcher3.dagger.LauncherAppComponent;
44 import com.android.launcher3.dagger.LauncherAppSingleton;
45 
46 import java.util.Collections;
47 import java.util.List;
48 import java.util.Map;
49 
50 import javax.inject.Inject;
51 
52 /**
53  * A wrapper for the hidden API calls
54  */
55 @LauncherAppSingleton
56 public class ApiWrapper {
57 
58     public static final DaggerSingletonObject<ApiWrapper> INSTANCE = new DaggerSingletonObject<>(
59             LauncherAppComponent::getApiWrapper);
60 
61     protected final Context mContext;
62     private final String[] mLegacyMultiInstanceSupportedApps;
63 
64     @Inject
ApiWrapper(@pplicationContext Context context)65     public ApiWrapper(@ApplicationContext Context context) {
66         mContext = context;
67         mLegacyMultiInstanceSupportedApps = context.getResources().getStringArray(
68                 com.android.launcher3.R.array.config_appsSupportMultiInstancesSplit);
69     }
70 
71     /**
72      * Returns the list of persons associated with the provided shortcut info
73      */
getPersons(ShortcutInfo si)74     public Person[] getPersons(ShortcutInfo si) {
75         return Utilities.EMPTY_PERSON_ARRAY;
76     }
77 
getActivityOverrides()78     public Map<String, LauncherActivityInfo> getActivityOverrides() {
79         return Collections.emptyMap();
80     }
81 
82     /**
83      * Creates an ActivityOptions to play fade-out animation on closing targets
84      */
createFadeOutAnimOptions()85     public ActivityOptions createFadeOutAnimOptions() {
86         return ActivityOptions.makeCustomAnimation(mContext, 0, android.R.anim.fade_out);
87     }
88 
89     /**
90      * Returns a map of all users on the device to their corresponding UI properties
91      */
queryAllUsers()92     public Map<UserHandle, UserIconInfo> queryAllUsers() {
93         UserManager um = mContext.getSystemService(UserManager.class);
94         Map<UserHandle, UserIconInfo> users = new ArrayMap<>();
95         List<UserHandle> usersActual = um.getUserProfiles();
96         if (usersActual != null) {
97             for (UserHandle user : usersActual) {
98                 long serial = um.getSerialNumberForUser(user);
99 
100                 // Simple check to check if the provided user is work profile
101                 // TODO: Migrate to a better platform API
102                 NoopDrawable d = new NoopDrawable();
103                 boolean isWork = (d != mContext.getPackageManager().getUserBadgedIcon(d, user));
104                 UserIconInfo info = new UserIconInfo(
105                         user,
106                         isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN,
107                         serial);
108                 users.put(user, info);
109             }
110         }
111         return users;
112     }
113 
114     /**
115      * Returns the list of the system packages that are installed at user creation.
116      * An empty list denotes that all system packages are installed for that user at creation.
117      */
getPreInstalledSystemPackages(UserHandle user)118     public List<String> getPreInstalledSystemPackages(UserHandle user) {
119         return Collections.emptyList();
120     }
121 
122     /**
123      * Returns an intent which can be used to start the App Market activity (Installer
124      * Activity).
125      */
getAppMarketActivityIntent(String packageName, UserHandle user)126     public Intent getAppMarketActivityIntent(String packageName, UserHandle user) {
127         return createMarketIntent(packageName);
128     }
129 
130     /**
131      * Returns an intent which can be used to start a search for a package on app market
132      */
getMarketSearchIntent(String packageName, UserHandle user)133     public Intent getMarketSearchIntent(String packageName, UserHandle user) {
134         // If we are search for the current user, just launch the market directly as the
135         // system won't have the installer details either
136         return  (Process.myUserHandle().equals(user))
137                 ? createMarketIntent(packageName)
138                 : getAppMarketActivityIntent(packageName, user);
139     }
140 
createMarketIntent(String packageName)141     private static Intent createMarketIntent(String packageName) {
142         return new Intent(Intent.ACTION_VIEW)
143                 .setData(new Uri.Builder()
144                         .scheme("market")
145                         .authority("details")
146                         .appendQueryParameter("id", packageName)
147                         .build())
148                 .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app")
149                         .authority(BuildConfig.APPLICATION_ID).build());
150     }
151 
152     /**
153      * Returns an intent which can be used to open Private Space Settings.
154      */
155     @Nullable
getPrivateSpaceSettingsIntent()156     public Intent getPrivateSpaceSettingsIntent() {
157         return null;
158     }
159 
160     /**
161      * Checks if an activity is flagged as non-resizeable.
162      */
isNonResizeableActivity(@onNull LauncherActivityInfo lai)163     public boolean isNonResizeableActivity(@NonNull LauncherActivityInfo lai) {
164         // Overridden in Quickstep
165         return false;
166     }
167 
168     /**
169      * Checks if an activity supports multi-instance.
170      */
supportsMultiInstance(@onNull LauncherActivityInfo lai)171     public boolean supportsMultiInstance(@NonNull LauncherActivityInfo lai) {
172         // Check app multi-instance properties after V
173         if (!Utilities.ATLEAST_V) {
174             return false;
175         }
176 
177         // Check the legacy hardcoded allowlist first
178         for (String pkg : mLegacyMultiInstanceSupportedApps) {
179             if (pkg.equals(lai.getComponentName().getPackageName())) {
180                 return true;
181             }
182         }
183 
184         // Overridden in Quickstep
185         return false;
186     }
187     /**
188      * Starts an Activity which can be used to set this Launcher as the HOME app, via a consent
189      * screen. In case the consent screen cannot be shown, or the user does not set current Launcher
190      * as HOME app, a toast asking the user to do the latter is shown.
191      */
assignDefaultHomeRole(Context context)192     public void assignDefaultHomeRole(Context context) {
193         RoleManager roleManager = context.getSystemService(RoleManager.class);
194         assert roleManager != null;
195         if (roleManager.isRoleAvailable(RoleManager.ROLE_HOME)
196                 && !roleManager.isRoleHeld(RoleManager.ROLE_HOME)) {
197             Intent roleRequestIntent = roleManager.createRequestRoleIntent(
198                     RoleManager.ROLE_HOME);
199             Launcher launcher = Launcher.getLauncher(context);
200             launcher.startActivityForResult(roleRequestIntent, REQUEST_HOME_ROLE);
201         }
202     }
203 
204     /**
205      * Returns a hash to uniquely identify a particular version of appInfo
206      */
getApplicationInfoHash(@onNull ApplicationInfo appInfo)207     public String getApplicationInfoHash(@NonNull ApplicationInfo appInfo) {
208         // The hashString in source dir changes with every install
209         return appInfo.sourceDir;
210     }
211 
212     /**
213      * Returns the round icon resource Id if defined by the app
214      */
getRoundIconRes(@onNull ApplicationInfo appInfo)215     public int getRoundIconRes(@NonNull ApplicationInfo appInfo) {
216         return 0;
217     }
218 
219     /**
220      * Checks if the shortcut is using an icon with file or URI source
221      */
isFileDrawable(@onNull ShortcutInfo shortcutInfo)222     public boolean isFileDrawable(@NonNull ShortcutInfo shortcutInfo) {
223         return false;
224     }
225 
226     private static class NoopDrawable extends ColorDrawable {
227         @Override
getIntrinsicHeight()228         public int getIntrinsicHeight() {
229             return 1;
230         }
231 
232         @Override
getIntrinsicWidth()233         public int getIntrinsicWidth() {
234             return 1;
235         }
236     }
237 }
238