Added Application Suggestions.
Added in custom Resolver to handle providing suggestions. Added in Service to handle providing suggestions to custom resolver. Added in ability to provider suggestions through a Proxy to another application which must be installed during compile time if one is to be used. This is a similar implementation to how the Location Services work. Change-Id: Id960260596b7bb6485caa1e1d07744e387a4c6e9
This commit is contained in:
parent
35df988aa5
commit
e78ca4d6fe
|
@ -463,6 +463,7 @@ package cyanogenmod.platform {
|
|||
|
||||
public static final class Manifest.permission {
|
||||
ctor public Manifest.permission();
|
||||
field public static final java.lang.String ACCESS_APP_SUGGESTIONS = "cyanogenmod.permission.ACCESS_APP_SUGGESTIONS";
|
||||
field public static final java.lang.String HARDWARE_ABSTRACTION_ACCESS = "cyanogenmod.permission.HARDWARE_ABSTRACTION_ACCESS";
|
||||
field public static final java.lang.String MANAGE_ALARMS = "cyanogenmod.permission.MANAGE_ALARMS";
|
||||
field public static final java.lang.String MANAGE_PERSISTENT_STORAGE = "cyanogenmod.permission.MANAGE_PERSISTENT_STORAGE";
|
||||
|
@ -482,10 +483,18 @@ package cyanogenmod.platform {
|
|||
ctor public R();
|
||||
}
|
||||
|
||||
public static final class R.array {
|
||||
ctor public R.array();
|
||||
}
|
||||
|
||||
public static final class R.attr {
|
||||
ctor public R.attr();
|
||||
}
|
||||
|
||||
public static final class R.bool {
|
||||
ctor public R.bool();
|
||||
}
|
||||
|
||||
public static final class R.drawable {
|
||||
ctor public R.drawable();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* Copyright (c) 2015, The CyanogenMod Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.cyanogenmod.platform.internal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import com.android.server.SystemService;
|
||||
|
||||
import cyanogenmod.app.CMContextConstants;
|
||||
import cyanogenmod.app.suggest.ApplicationSuggestion;
|
||||
import cyanogenmod.app.suggest.IAppSuggestManager;
|
||||
import cyanogenmod.platform.Manifest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AppSuggestManagerService extends SystemService {
|
||||
private static final String TAG = "AppSgstMgrService";
|
||||
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
public static final String NAME = "appsuggest";
|
||||
|
||||
public static final String ACTION = "org.cyanogenmod.app.suggest";
|
||||
|
||||
private AppSuggestProviderInterface mImpl;
|
||||
|
||||
private final IBinder mService = new IAppSuggestManager.Stub() {
|
||||
public boolean handles(Intent intent) {
|
||||
if (mImpl == null) return false;
|
||||
|
||||
return mImpl.handles(intent);
|
||||
}
|
||||
|
||||
public List<ApplicationSuggestion> getSuggestions(Intent intent) {
|
||||
if (mImpl == null) return new ArrayList<>(0);
|
||||
|
||||
return mImpl.getSuggestions(intent);
|
||||
}
|
||||
};
|
||||
|
||||
public AppSuggestManagerService(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mImpl = AppSuggestProviderProxy.createAndBind(mContext, TAG, ACTION,
|
||||
R.bool.config_enableAppSuggestOverlay,
|
||||
R.string.config_appSuggestProviderPackageName,
|
||||
R.array.config_appSuggestProviderPackageNames);
|
||||
if (mImpl == null) {
|
||||
Slog.e(TAG, "no app suggest provider found");
|
||||
} else {
|
||||
Slog.i(TAG, "Bound to to suggest provider");
|
||||
}
|
||||
|
||||
publishBinderService(CMContextConstants.CM_APP_SUGGEST_SERVICE, mService);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (c) 2015, The CyanogenMod Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.cyanogenmod.platform.internal;
|
||||
|
||||
import android.content.Intent;
|
||||
import cyanogenmod.app.suggest.ApplicationSuggestion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* App Suggestion Manager's interface for Applicaiton Suggestion Providers.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface AppSuggestProviderInterface {
|
||||
boolean handles(Intent intent);
|
||||
List<ApplicationSuggestion> getSuggestions(Intent intent);
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* Copyright (c) 2015, The CyanogenMod Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.cyanogenmod.platform.internal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import com.android.server.ServiceWatcher;
|
||||
|
||||
import cyanogenmod.app.suggest.ApplicationSuggestion;
|
||||
import cyanogenmod.app.suggest.IAppSuggestProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public class AppSuggestProviderProxy implements AppSuggestProviderInterface {
|
||||
private static final String TAG = AppSuggestProviderProxy.class.getSimpleName();
|
||||
private static final boolean DEBUG = AppSuggestManagerService.DEBUG;
|
||||
|
||||
public static AppSuggestProviderProxy createAndBind(
|
||||
Context context, String name, String action,
|
||||
int overlaySwitchResId, int defaultServicePackageNameResId,
|
||||
int initialPackageNamesResId) {
|
||||
AppSuggestProviderProxy proxy = new AppSuggestProviderProxy(context, name, action,
|
||||
overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId);
|
||||
if (proxy.bind()) {
|
||||
return proxy;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private ServiceWatcher mServiceWatcher;
|
||||
|
||||
private AppSuggestProviderProxy(Context context, String name, String action,
|
||||
int overlaySwitchResId, int defaultServicePackageNameResId,
|
||||
int initialPackageNamesResId) {
|
||||
mContext = context;
|
||||
mServiceWatcher = new ServiceWatcher(mContext, TAG + "-" + name, action, overlaySwitchResId,
|
||||
defaultServicePackageNameResId, initialPackageNamesResId, null, null);
|
||||
}
|
||||
|
||||
private boolean bind() {
|
||||
return mServiceWatcher.start();
|
||||
}
|
||||
|
||||
private IAppSuggestProvider getService() {
|
||||
return IAppSuggestProvider.Stub.asInterface(mServiceWatcher.getBinder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handles(Intent intent) {
|
||||
IAppSuggestProvider service = getService();
|
||||
if (service == null) return false;
|
||||
|
||||
try {
|
||||
return service.handles(intent);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
} catch (Exception e) {
|
||||
// never let remote service crash system server
|
||||
Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ApplicationSuggestion> getSuggestions(Intent intent) {
|
||||
IAppSuggestProvider service = getService();
|
||||
if (service == null) return new ArrayList<>(0);
|
||||
|
||||
try {
|
||||
return service.getSuggestions(intent);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, e);
|
||||
} catch (Exception e) {
|
||||
// never let remote service crash system server
|
||||
Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
|
||||
}
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
}
|
|
@ -120,6 +120,13 @@
|
|||
android:description="@string/permdesc_managePersistentStorage"
|
||||
android:protectionLevel="system|signature" />
|
||||
|
||||
<!-- Permission for accessing a provider of app suggestions
|
||||
@hide -->
|
||||
<permission android:name="cyanogenmod.permission.ACCESS_APP_SUGGESTIONS"
|
||||
android:label="@string/permlab_accessAppSuggestions"
|
||||
android:description="@string/permdesc_accessAppSuggestions"
|
||||
android:protectionLevel="signature|system|development" />
|
||||
|
||||
<application android:process="system"
|
||||
android:persistent="true"
|
||||
android:hasCode="false"
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 The CyanogenMod Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Whether to enable app suggest overlay which allows app suggest
|
||||
provider to be replaced by an app at run-time. When disabled, only
|
||||
the config_appSuggestProviderPackageName will be searched for app
|
||||
suggest provider, otherwise packages whos signature matches the
|
||||
signature of config_appSuggestProviderPackageNames will be searched,
|
||||
and the service with the highest version number will be picked.
|
||||
Anyone who wants to disable the overlay mechanism can set it to false.
|
||||
|
||||
Note: There appears to be an issue with false if we reinstall the provider which causes
|
||||
it to not get the update and fail to reconnect on package update. It's safer to just
|
||||
use the list version with config_appSuggestProviderPackageNames.
|
||||
-->
|
||||
<bool name="config_enableAppSuggestOverlay" translatable="false">true</bool>
|
||||
|
||||
<!-- Package name providing app suggest support. Used only when
|
||||
config_enableAppSuggestOverlay is false. -->
|
||||
<string name="config_appSuggestProviderPackageName" translatable="false">com.cyanogen.app.suggest</string>
|
||||
|
||||
<!-- List of packages providing app suggest support. Used only when
|
||||
config_enableAppSuggestOverlay is true. -->
|
||||
<string-array name="config_appSuggestProviderPackageNames" translatable="false">
|
||||
<item>com.cyanogen.app.suggest</item>
|
||||
</string-array>
|
||||
</resources>
|
|
@ -70,6 +70,10 @@
|
|||
<string name="permlab_managePersistentStorage">manage persistent storage</string>
|
||||
<string name="permdesc_managePersistentStorage">Allows an app to read or write properties which may persist thrοugh a factory reset.</string>
|
||||
|
||||
<!-- Labels for the ACCESS_APP_SUGGESTIONS permission -->
|
||||
<string name="permlab_accessAppSuggestions">access application suggestions</string>
|
||||
<string name="permdesc_accessAppSuggestions">Allows an app to access application suggestions.</string>
|
||||
|
||||
<!-- Label to show for a service that is running because it is observing the user's custom tiles. -->
|
||||
<string name="custom_tile_listener_binding_label">Custom tile listener</string>
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
SDK. Instead, put them here. -->
|
||||
<private-symbols package="org.cyanogenmod.platform.internal" />
|
||||
|
||||
<java-symbol type="bool" name="config_enableAppSuggestOverlay"/>
|
||||
<java-symbol type="string" name="config_appSuggestProviderPackageName"/>
|
||||
<java-symbol type="array" name="config_appSuggestProviderPackageNames"/>
|
||||
|
||||
<java-symbol type="string" name="custom_tile_listener_binding_label" />
|
||||
|
||||
<!-- Profiles -->
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# Copyright (C) 2015 The CyanogenMod Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
src_dir := src
|
||||
res_dir := res
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, $(src_dir))
|
||||
LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dir))
|
||||
|
||||
LOCAL_PACKAGE_NAME := CMResolver
|
||||
LOCAL_CERTIFICATE := platform
|
||||
LOCAL_PRIVILEGED_MODULE := true
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
org.cyanogenmod.platform.sdk
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
########################
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2015 The CyanogenMod Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:internal="http://schemas.android.com/apk/prv/res/android"
|
||||
package="org.cyanogenmod.resolver"
|
||||
coreApp="true"
|
||||
android:sharedUserId="android.uid.system">
|
||||
<!-- It is necessary to be a system app in order to update table versions in SystemProperties for
|
||||
CMSettings to know whether or not the client side cache is up to date. It is also necessary
|
||||
to run in the system process in order to start the content provider prior to running migration
|
||||
for CM settings on user starting -->
|
||||
|
||||
<uses-permission android:name="cyanogenmod.permission.ACCESS_APP_SUGGESTIONS" />
|
||||
|
||||
<application android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
android:killAfterRestore="false"
|
||||
android:allowClearUserData="false"
|
||||
android:supportsRtl="true"
|
||||
android:enabled="true">
|
||||
|
||||
<activity android:name="org.cyanogenmod.resolver.ResolverActivity"
|
||||
android:theme="@style/AppTheme.DeviceDefault.Resolver"
|
||||
android:exported="true"/>
|
||||
|
||||
</application>
|
||||
</manifest>
|
Binary file not shown.
After Width: | Height: | Size: 377 B |
Binary file not shown.
After Width: | Height: | Size: 274 B |
Binary file not shown.
After Width: | Height: | Size: 424 B |
Binary file not shown.
After Width: | Height: | Size: 567 B |
Binary file not shown.
After Width: | Height: | Size: 762 B |
Binary file not shown.
After Width: | Height: | Size: 990 B |
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/* //device/apps/common/res/any/layout/resolve_list_item.xml
|
||||
**
|
||||
** Copyright 2006, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/suggest_item_container"
|
||||
android:orientation="horizontal"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:background="?android:attr/activatedBackgroundIndicator">
|
||||
|
||||
<!-- Activity icon when presenting dialog
|
||||
Size will be filled in by ResolverActivity -->
|
||||
<ImageView android:id="@android:id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<!-- Activity name -->
|
||||
<TextView android:id="@android:id/text1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@android:id/icon"
|
||||
android:layout_toStartOf="@android:id/icon2"
|
||||
android:layout_centerVertical="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:minLines="1"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="marquee" />
|
||||
|
||||
<ImageView android:id="@android:id/icon2"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/play_download"/>
|
||||
</RelativeLayout>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014-2015 The CyanogenMod Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<string name="app_name">CyanogenMod Resolver</string>
|
||||
<string name="download_and_open_with">Download and open with</string>
|
||||
</resources>
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014-2015 The CyanogenMod Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<style name="AppTheme.DeviceDefault.Resolver" parent="@android:style/Theme.Material.Light">
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:backgroundDimEnabled">true</item>
|
||||
<item name="android:windowTranslucentStatus">false</item>
|
||||
<item name="android:windowTranslucentNavigation">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="android:colorControlActivated">?android:attr/colorControlHighlight</item>
|
||||
<item name="android:listPreferredItemPaddingStart">?android:attr/dialogPreferredPadding</item>
|
||||
<item name="android:listPreferredItemPaddingEnd">?android:attr/dialogPreferredPadding</item>
|
||||
</style>
|
||||
</resources>
|
File diff suppressed because it is too large
Load Diff
|
@ -85,4 +85,9 @@ public final class CMContextConstants {
|
|||
* @hide
|
||||
*/
|
||||
public static final String CM_HARDWARE_SERVICE = "cmhardware";
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final String CM_APP_SUGGEST_SERVICE = "cmappsuggest";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* Copyright (c) 2015, The CyanogenMod Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cyanogenmod.app.suggest;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import cyanogenmod.app.CMContextConstants;
|
||||
import cyanogenmod.app.suggest.ApplicationSuggestion;
|
||||
|
||||
/**
|
||||
* Provides an interface to get information about suggested apps for an intent which may include
|
||||
* applications not installed on the device. This is used by the CMResolver in order to provide
|
||||
* suggestions when an intent is fired but no application exists for the given intent.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class AppSuggestManager {
|
||||
private static final String TAG = AppSuggestManager.class.getSimpleName();
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
private static IAppSuggestManager sImpl;
|
||||
|
||||
private static AppSuggestManager sInstance;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
/**
|
||||
* Gets an instance of the AppSuggestManager.
|
||||
*
|
||||
* @param context
|
||||
*
|
||||
* @return An instance of the AppSuggestManager
|
||||
*/
|
||||
public static synchronized AppSuggestManager getInstance(Context context) {
|
||||
if (sInstance != null) {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
context = context.getApplicationContext() != null ? context.getApplicationContext() : context;
|
||||
|
||||
sInstance = new AppSuggestManager(context);
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private AppSuggestManager(Context context) {
|
||||
mContext = context.getApplicationContext();
|
||||
}
|
||||
|
||||
private static synchronized IAppSuggestManager getService() {
|
||||
if (sImpl == null) {
|
||||
IBinder b = ServiceManager.getService(CMContextConstants.CM_APP_SUGGEST_SERVICE);
|
||||
if (b != null) {
|
||||
sImpl = IAppSuggestManager.Stub.asInterface(b);
|
||||
} else {
|
||||
Log.e(TAG, "Unable to find implementation for app suggest service");
|
||||
}
|
||||
}
|
||||
|
||||
return sImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if an intent is handled by the App Suggestions Service. This should be
|
||||
* implemented in such a way that it is safe to call inline on the UI Thread.
|
||||
*
|
||||
* @param intent The intent
|
||||
* @return true if the App Suggestions Service has suggestions for this intent, false otherwise
|
||||
*/
|
||||
public boolean handles(Intent intent) {
|
||||
IAppSuggestManager mgr = getService();
|
||||
if (mgr == null) return false;
|
||||
try {
|
||||
return mgr.handles(intent);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Gets a list of the suggestions for the given intent.
|
||||
*
|
||||
* @param intent The intent
|
||||
* @return A list of application suggestions or an empty list if none.
|
||||
*/
|
||||
public List<ApplicationSuggestion> getSuggestions(Intent intent) {
|
||||
IAppSuggestManager mgr = getService();
|
||||
if (mgr == null) return new ArrayList<>(0);
|
||||
try {
|
||||
return mgr.getSuggestions(intent);
|
||||
} catch (RemoteException e) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the icon for the given suggestion.
|
||||
*
|
||||
* @param suggestion The suggestion to load the icon for
|
||||
*
|
||||
* @return A {@link Drawable} or null if one cannot be found
|
||||
*/
|
||||
public Drawable loadIcon(ApplicationSuggestion suggestion) {
|
||||
try {
|
||||
InputStream is = mContext.getContentResolver()
|
||||
.openInputStream(suggestion.getThumbailUri());
|
||||
return Drawable.createFromStream(is, null);
|
||||
} catch (FileNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright (c) 2015, The CyanogenMod Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cyanogenmod.app.suggest;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
parcelable ApplicationSuggestion;
|
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
* Copyright (c) 2015, The CyanogenMod Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cyanogenmod.app.suggest;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import cyanogenmod.os.Build;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public class ApplicationSuggestion implements Parcelable {
|
||||
|
||||
public static final Creator<ApplicationSuggestion> CREATOR =
|
||||
new Creator<ApplicationSuggestion>() {
|
||||
public ApplicationSuggestion createFromParcel(Parcel in) {
|
||||
return new ApplicationSuggestion(in);
|
||||
}
|
||||
|
||||
public ApplicationSuggestion[] newArray(int size) {
|
||||
return new ApplicationSuggestion[size];
|
||||
}
|
||||
};
|
||||
|
||||
private String mName;
|
||||
|
||||
private String mPackage;
|
||||
|
||||
private Uri mDownloadUri;
|
||||
|
||||
private Uri mThumbnailUri;
|
||||
|
||||
public ApplicationSuggestion(@NonNull String name, @NonNull String pkg,
|
||||
@NonNull Uri downloadUri, @NonNull Uri thumbnailUri) {
|
||||
mName = name;
|
||||
mPackage = pkg;
|
||||
mDownloadUri = downloadUri;
|
||||
mThumbnailUri = thumbnailUri;
|
||||
}
|
||||
|
||||
private ApplicationSuggestion(Parcel in) {
|
||||
// Read parcelable version, make sure to define explicit changes
|
||||
// within {@link Build.PARCELABLE_VERSION);
|
||||
int parcelableVersion = in.readInt();
|
||||
int parcelableSize = in.readInt();
|
||||
int startPosition = in.dataPosition();
|
||||
|
||||
if (parcelableVersion >= Build.CM_VERSION_CODES.APRICOT) {
|
||||
mName = in.readString();
|
||||
mPackage = in.readString();
|
||||
mDownloadUri = in.readParcelable(Uri.class.getClassLoader());
|
||||
mThumbnailUri = in.readParcelable(Uri.class.getClassLoader());
|
||||
}
|
||||
|
||||
in.setDataPosition(startPosition + parcelableSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
// Write parcelable version, make sure to define explicit changes
|
||||
// within {@link Build.PARCELABLE_VERSION);
|
||||
out.writeInt(Build.PARCELABLE_VERSION);
|
||||
|
||||
// Inject a placeholder that will store the parcel size from this point on
|
||||
// (not including the size itself).
|
||||
int sizePosition = out.dataPosition();
|
||||
out.writeInt(0);
|
||||
int startPosition = out.dataPosition();
|
||||
|
||||
out.writeString(mName);
|
||||
out.writeString(mPackage);
|
||||
out.writeParcelable(mDownloadUri, flags);
|
||||
out.writeParcelable(mThumbnailUri, flags);
|
||||
|
||||
// Go back and write size
|
||||
int parcelableSize = out.dataPosition() - startPosition;
|
||||
out.setDataPosition(sizePosition);
|
||||
out.writeInt(parcelableSize);
|
||||
out.setDataPosition(startPosition + parcelableSize);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return mPackage;
|
||||
}
|
||||
|
||||
public Uri getDownloadUri() {
|
||||
return mDownloadUri;
|
||||
}
|
||||
|
||||
public Uri getThumbailUri() {
|
||||
return mThumbnailUri;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2015, The CyanogenMod Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cyanogenmod.app.suggest;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import cyanogenmod.app.suggest.ApplicationSuggestion;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
interface IAppSuggestManager {
|
||||
boolean handles(in Intent intent);
|
||||
|
||||
List<ApplicationSuggestion> getSuggestions(in Intent intent);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2015, The CyanogenMod Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cyanogenmod.app.suggest;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import cyanogenmod.app.suggest.ApplicationSuggestion;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
interface IAppSuggestProvider {
|
||||
boolean handles(in Intent intent);
|
||||
|
||||
List<ApplicationSuggestion> getSuggestions(in Intent intent);
|
||||
}
|
|
@ -463,6 +463,7 @@ package cyanogenmod.platform {
|
|||
|
||||
public static final class Manifest.permission {
|
||||
ctor public Manifest.permission();
|
||||
field public static final java.lang.String ACCESS_APP_SUGGESTIONS = "cyanogenmod.permission.ACCESS_APP_SUGGESTIONS";
|
||||
field public static final java.lang.String HARDWARE_ABSTRACTION_ACCESS = "cyanogenmod.permission.HARDWARE_ABSTRACTION_ACCESS";
|
||||
field public static final java.lang.String MANAGE_ALARMS = "cyanogenmod.permission.MANAGE_ALARMS";
|
||||
field public static final java.lang.String MANAGE_PERSISTENT_STORAGE = "cyanogenmod.permission.MANAGE_PERSISTENT_STORAGE";
|
||||
|
@ -482,10 +483,18 @@ package cyanogenmod.platform {
|
|||
ctor public R();
|
||||
}
|
||||
|
||||
public static final class R.array {
|
||||
ctor public R.array();
|
||||
}
|
||||
|
||||
public static final class R.attr {
|
||||
ctor public R.attr();
|
||||
}
|
||||
|
||||
public static final class R.bool {
|
||||
ctor public R.bool();
|
||||
}
|
||||
|
||||
public static final class R.drawable {
|
||||
ctor public R.drawable();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue