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:
herriojr 2015-09-08 13:59:20 -07:00
parent 35df988aa5
commit e78ca4d6fe
27 changed files with 2274 additions and 0 deletions

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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"

View File

@ -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>

View File

@ -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>

View File

@ -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 -->

View File

@ -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))

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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";
}

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();
}