/* * 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; import java.util.UUID; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.NotificationGroup; import android.content.Context; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; import android.util.Log; import cyanogenmod.app.IProfileManager; import com.android.internal.R; /** *

* The ProfileManager allows you to create {@link Profile}s and {@link ProfileGroup}s to create * specific behavior states depending on triggers from hardware devices changing states, such as: * * WiFi being enabled * WiFi connecting to a certain AP * Bluetooth connecting to a certain device * Bluetooth disconnecting to a certain device * NFC tag being scanned * * Depending on these triggers, you can override connection settings, lockscreen modes, media * stream volumes and various other settings. *

* * To get the instance of this class, utilize ProfileManager#getInstance(Context context) * * This manager requires the {@link cyanogenmod.platform.Manifest.permission.MODIFY_PROFILES} * permission. * * @see cyanogenmod.app.Profile * @see cyanogenmod.app.ProfileGroup */ public class ProfileManager { private static IProfileManager sService; private Context mContext; private static final String TAG = "ProfileManager"; private static final String SYSTEM_PROFILES_ENABLED = "system_profiles_enabled"; /** *

Broadcast Action: A new profile has been selected. This can be triggered by the user * or by calls to the ProfileManagerService / Profile.

*/ public static final String INTENT_ACTION_PROFILE_SELECTED = "cyanogenmod.platform.intent.action.PROFILE_SELECTED"; /** *

Broadcast Action: Current profile has been updated. This is triggered every time the * currently active profile is updated, instead of selected.

*

For instance, this includes profile updates caused by a locale change, which doesn't * trigger a profile selection, but causes its name to change.

*/ public static final String INTENT_ACTION_PROFILE_UPDATED = "cyanogenmod.platform.intent.action.PROFILE_UPDATED"; /** * Extra for {@link #INTENT_ACTION_PROFILE_SELECTED} and {@link #INTENT_ACTION_PROFILE_UPDATED}: * The name of the newly activated or updated profile */ public static final String EXTRA_PROFILE_NAME = "name"; /** * Extra for {@link #INTENT_ACTION_PROFILE_SELECTED} and {@link #INTENT_ACTION_PROFILE_UPDATED}: * The string representation of the UUID of the newly activated or updated profile */ public static final String EXTRA_PROFILE_UUID = "uuid"; /** * Extra for {@link #INTENT_ACTION_PROFILE_SELECTED}: * The name of the previously active profile */ public static final String EXTRA_LAST_PROFILE_NAME = "lastName"; /** * Extra for {@link #INTENT_ACTION_PROFILE_SELECTED}: * The string representation of the UUID of the previously active profile */ public static final String EXTRA_LAST_PROFILE_UUID = "uuid"; /** * Activity Action: Shows a profile picker. *

* Input: {@link #EXTRA_PROFILE_EXISTING_UUID}, {@link #EXTRA_PROFILE_SHOW_NONE}, * {@link #EXTRA_PROFILE_TITLE}. *

* Output: {@link #EXTRA_PROFILE_PICKED_UUID}. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_PROFILE_PICKER = "cyanogenmod.platform.intent.action.PROFILE_PICKER"; /** * Constant for NO_PROFILE */ public static final UUID NO_PROFILE = UUID.fromString("00000000-0000-0000-0000-000000000000"); /** * Given to the profile picker as a boolean. Whether to show an item for * deselect the profile. If the "None" item is picked, * {@link #EXTRA_PROFILE_PICKED_UUID} will be {@link #NO_PROFILE}. * * @see #ACTION_PROFILE_PICKER */ public static final String EXTRA_PROFILE_SHOW_NONE = "cyanogenmod.platform.intent.extra.profile.SHOW_NONE"; /** * Given to the profile picker as a {@link UUID} string representation. The {@link UUID} * representation of the current profile, which will be used to show a checkmark next to * the item for this {@link UUID}. If the item is {@link #NO_PROFILE} then "None" item * is selected if {@link #EXTRA_PROFILE_SHOW_NONE} is enabled. Otherwise, the current * profile is selected. * * @see #ACTION_PROFILE_PICKER */ public static final String EXTRA_PROFILE_EXISTING_UUID = "cyanogenmod.platform.extra.profile.EXISTING_UUID"; /** * Given to the profile picker as a {@link CharSequence}. The title to * show for the profile picker. This has a default value that is suitable * in most cases. * * @see #ACTION_PROFILE_PICKER */ public static final String EXTRA_PROFILE_TITLE = "cyanogenmod.platform.intent.extra.profile.TITLE"; /** * Returned from the profile picker as a {@link UUID} string representation. *

* It will be one of: *

  • the picked profile, *
  • null if the "None" item was picked. * * @see #ACTION_PROFILE_PICKER */ public static final String EXTRA_PROFILE_PICKED_UUID = "cyanogenmod.platform.intent.extra.profile.PICKED_UUID"; /** * Broadcast intent action indicating that Profiles has been enabled or disabled. * One extra provides this state as an int. * * @see #EXTRA_PROFILES_STATE */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String PROFILES_STATE_CHANGED_ACTION = "cyanogenmod.platform.app.profiles.PROFILES_STATE_CHANGED"; /** * The lookup key for an int that indicates whether Profiles are enabled or * disabled. Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. * * @see #PROFILES_STATE_DISABLED * @see #PROFILES_STATE_ENABLED */ public static final String EXTRA_PROFILES_STATE = "profile_state"; /** * Set the resource id theme to use for the dialog picker activity.
    * The default theme is com.android.internal.R.Theme_Holo_Dialog_Alert. * * @see #ACTION_PROFILE_PICKER */ public static final String EXTRA_PROFILE_DIALOG_THEME = "cyanogenmod.platform.intent.extra.profile.DIALOG_THEME"; /** * Profiles are disabled. * * @see #PROFILES_STATE_CHANGED_ACTION */ public static final int PROFILES_STATE_DISABLED = 0; /** * Profiles are enabled. * * @see #PROFILES_STATE_CHANGED_ACTION */ public static final int PROFILES_STATE_ENABLED = 1; // A blank profile that is created to be returned if profiles disabled private static Profile mEmptyProfile; private static ProfileManager sProfileManagerInstance; private ProfileManager(Context context) { Context appContext = context.getApplicationContext(); if (appContext != null) { mContext = appContext; } else { mContext = context; } sService = getService(); mEmptyProfile = new Profile("EmptyProfile"); } /** * Get or create an instance of the {@link cyanogenmod.app.ProfileManager} * @param context * @return {@link ProfileManager} */ public static ProfileManager getInstance(Context context) { if (sProfileManagerInstance == null) { sProfileManagerInstance = new ProfileManager(context); } return sProfileManagerInstance; } /** @hide */ static public IProfileManager getService() { if (sService != null) { return sService; } IBinder b = ServiceManager.getService(CMContextConstants.CM_PROFILE_SERVICE); sService = IProfileManager.Stub.asInterface(b); return sService; } @Deprecated public void setActiveProfile(String profileName) { if (Settings.System.getInt(mContext.getContentResolver(), SYSTEM_PROFILES_ENABLED, 1) == 1) { // Profiles are enabled, return active profile try { getService().setActiveProfileByName(profileName); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } } } /** * Set the active {@link Profile} by {@link UUID} * @param profileUuid the {@link UUID} associated with the profile */ public void setActiveProfile(UUID profileUuid) { if (Settings.System.getInt(mContext.getContentResolver(), SYSTEM_PROFILES_ENABLED, 1) == 1) { // Profiles are enabled, return active profile try { getService().setActiveProfile(new ParcelUuid(profileUuid)); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } } } /** * Get the active {@link Profile} * @return active {@link Profile} */ public Profile getActiveProfile() { if (Settings.System.getInt(mContext.getContentResolver(), SYSTEM_PROFILES_ENABLED, 1) == 1) { // Profiles are enabled, return active profile try { return getService().getActiveProfile(); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } return null; } else { // Profiles are not enabled, return the empty profile return mEmptyProfile; } } /** * Add a {@link Profile} that can be selected by the user * @param profile a {@link Profile} object */ public void addProfile(Profile profile) { try { getService().addProfile(profile); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } } /** * Remove a {@link Profile} from user selection * @param profile a {@link Profile} object */ public void removeProfile(Profile profile) { try { getService().removeProfile(profile); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } } /** * Update a {@link Profile} object * @param profile a {@link Profile} object */ public void updateProfile(Profile profile) { try { getService().updateProfile(profile); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } } /** * Get the {@link Profile} object by its literal name * @param profileName name associated with the profile * @return profile a {@link Profile} object */ @Deprecated public Profile getProfile(String profileName) { try { return getService().getProfileByName(profileName); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } return null; } /** * Get a {@link Profile} via {@link UUID} * @param profileUuid {@link UUID} associated with the profile * @return {@link Profile} */ public Profile getProfile(UUID profileUuid) { try { return getService().getProfile(new ParcelUuid(profileUuid)); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } return null; } /** * Get the profile names currently available to the user * @return {@link String[]} of profile names */ public String[] getProfileNames() { try { Profile[] profiles = getService().getProfiles(); String[] names = new String[profiles.length]; for (int i = 0; i < profiles.length; i++) { names[i] = profiles[i].getName(); } return names; } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } return null; } /** * Get the {@link Profile}s currently available to the user * @return {@link Profile[]} */ public Profile[] getProfiles() { try { return getService().getProfiles(); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } return null; } /** * Check if a {@link Profile} exists via its literal name * @param profileName a profile name * @return whether or not the profile exists */ public boolean profileExists(String profileName) { try { return getService().profileExistsByName(profileName); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); // To be on the safe side, we'll return "true", to prevent duplicate profiles // from being created. return true; } } /** * Check if a {@link Profile} exists via its {@link UUID} * @param profileUuid the profiles {@link UUID} * @return whether or not the profile exists */ public boolean profileExists(UUID profileUuid) { try { return getService().profileExists(new ParcelUuid(profileUuid)); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); // To be on the safe side, we'll return "true", to prevent duplicate profiles // from being created. return true; } } /** * Check if a NotificationGroup exists * @param notificationGroupName the name of the notification group * @return whether or not the notification group exists * @hide */ public boolean notificationGroupExists(String notificationGroupName) { try { return getService().notificationGroupExistsByName(notificationGroupName); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); // To be on the safe side, we'll return "true", to prevent duplicate notification // groups from being created. return true; } } /** * Get the currently available NotificationGroups * @return NotificationGroup * @hide */ public NotificationGroup[] getNotificationGroups() { try { return getService().getNotificationGroups(); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } return null; } /** * Add a NotificationGroup to the available list * @param group NotificationGroup * @hide */ public void addNotificationGroup(NotificationGroup group) { try { getService().addNotificationGroup(group); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } } /** * Remove a NotificationGroup from the available list * @param group NotificationGroup * @hide */ public void removeNotificationGroup(NotificationGroup group) { try { getService().removeNotificationGroup(group); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } } /** * Update a NotificationGroup from the available list * @param group NotificationGroup * @hide */ public void updateNotificationGroup(NotificationGroup group) { try { getService().updateNotificationGroup(group); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } } /** * Get a NotificationGroup for a specific package * @param pkg name of the package * @hide */ public NotificationGroup getNotificationGroupForPackage(String pkg) { try { return getService().getNotificationGroupForPackage(pkg); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } return null; } /** * Get a NotificationGroup from the available list via {@link UUID} * @param uuid {@link UUID} of the notification group * @hide */ public NotificationGroup getNotificationGroup(UUID uuid) { try { return getService().getNotificationGroup(new ParcelUuid(uuid)); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } return null; } /** * Get an active {@link ProfileGroup} via its package name * @param packageName the package name associated to the profile group * @return {@link ProfileGroup} * @hide */ public ProfileGroup getActiveProfileGroup(String packageName) { NotificationGroup notificationGroup = getNotificationGroupForPackage(packageName); if (notificationGroup == null) { ProfileGroup defaultGroup = getActiveProfile().getDefaultGroup(); return defaultGroup; } return getActiveProfile().getProfileGroup(notificationGroup.getUuid()); } /** * Reset all profiles, groups, and notification groups to default state */ public void resetAll() { try { getService().resetAll(); } catch (RemoteException e) { Log.e(TAG, e.getLocalizedMessage(), e); } catch (SecurityException e) { Log.e(TAG, e.getLocalizedMessage(), e); } } }