blob: ddf6dfdd8670bcaf74bc5db52e4d799d4bd9c500 [file] [log] [blame]
/*
* Copyright (C) 2013 Fairphone 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 com.fairphone.fplauncher3.widgets.appswitcher;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.fairphone.fplauncher3.R;
import com.fairphone.fplauncher3.applifecycle.AppDrawerView;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
/**
* Represents the run data for a specific application in the system.
* It contains data for fast access like the component name and the icon.
* All the info can still be obtained via the Application info.
*
*/
public class ApplicationRunInformation
{
private static final int APP_RARE_USE_DAYS = 365;
private static final String TAG = ApplicationRunInformation.class.getSimpleName();
private static final String APP_RUN_INFO_SEPARATOR = ";";
private static final String COMPONENT_NAME_SEPARATOR = ";";
public static final long HOURS_IN_A_DAY = 24L;
public static final long MINUTES_IN_HOUR = 60L;
public static final long SECONDS_IN_MINUTE = 60L;
public static final long MILLIS_IN_SECOND = 1000L;
private ComponentName mComponentName;
private int mRunCount;
private Date mLastExecution;
private boolean mIsNewApp;
private boolean mIsPinnedApp;
private boolean mIsUpdatedApp;
private APP_AGE mAppAge;
/**
* Create a base count zero Application Run information.
*
* @param component The ComponentName of the application
*/
public ApplicationRunInformation(ComponentName component){
this(component, 0);
}
/**
* Create a application run information with a specific value for the count
* the count value must be zero or above.
*
* @param component The ComponentName of the application
* @param count the number of run times (used when starting)
*/
public ApplicationRunInformation(ComponentName component, int count) {
if(component == null){
throw new IllegalArgumentException("Invalid value for ComponentName");
}
setComponentName(component);
if(count < 0){
throw new IllegalArgumentException("Run count cannot be negative");
}
mRunCount = count;
}
public int getCount(){
return mRunCount;
}
public void incrementCount(){
mRunCount++;
}
public void decrementCount(){
if(mRunCount > 0){
mRunCount--;
}
}
public ComponentName getComponentName() {
return mComponentName;
}
private void setComponentName(ComponentName component) {
this.mComponentName = new ComponentName(component.getPackageName(), component.getClassName());
}
public Date getLastExecution() {
return mLastExecution;
}
public void setLastExecution(Date lastExecution) {
this.mLastExecution = lastExecution;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((mComponentName == null) ? 0 : mComponentName.hashCode());
result = prime * result
+ ((mLastExecution == null) ? 0 : mLastExecution.hashCode());
result = prime * result + mRunCount;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ApplicationRunInformation other = (ApplicationRunInformation) obj;
if (mComponentName == null) {
if (other.mComponentName != null) {
return false;
}
} else if (!mComponentName.equals(other.mComponentName)) {
return false;
}
if (mLastExecution == null) {
if (other.mLastExecution != null) {
return false;
}
} else if (!mLastExecution.equals(other.mLastExecution)) {
return false;
}
if (mRunCount != other.mRunCount) {
return false;
}
return true;
}
public void resetCount() {
mRunCount = 0;
}
/**
* Serializes a component in order to be used has a map key
* @param componentName component to serialize
* @return the serialized component
*/
public static String serializeComponentName(ComponentName componentName) {
StringBuffer sb = new StringBuffer();
sb.append(componentName.getPackageName()).append(COMPONENT_NAME_SEPARATOR).append(componentName.getClassName());
return sb.toString();
}
/**
* Transforms a string into a ComponentName
* @param componentNameString serialized component
* @return the ComponentName object
*/
public static ComponentName deserializeComponentName(String componentNameString) {
String[] strings = componentNameString.split(COMPONENT_NAME_SEPARATOR);
return strings.length == 2 ? new ComponentName(strings[0],strings[1]): null;
}
public boolean isNewApp() {
return mIsNewApp;
}
public void setIsNewApp(boolean isNewApp) {
this.mIsNewApp = isNewApp;
}
public boolean isUpdatedApp() {
return mIsUpdatedApp;
}
public void setIsUpdatedApp(boolean isUpdatedApp)
{
this.mIsUpdatedApp = isUpdatedApp;
}
public boolean isPinnedApp() {
return mIsPinnedApp;
}
public void setIsPinnedApp(boolean isPinnedApp) {
this.mIsPinnedApp = isPinnedApp;
}
public static void persistAppRunInfo(Context context, String preferencesKey, List<ApplicationRunInformation> appsToSave)
{
SharedPreferences prefs = context.getSharedPreferences(preferencesKey, 0);
// get the current prefs and clear to update
android.content.SharedPreferences.Editor editor = prefs.edit();
editor.clear();
for (ApplicationRunInformation appInfo : appsToSave)
{
String appSerialized = ApplicationRunInformation.serializeApplicationRunInformation(appInfo);
editor.putString(ApplicationRunInformation.serializeComponentName(appInfo.getComponentName()), appSerialized);
}
editor.commit();
}
public static List<ApplicationRunInformation> loadAppRunInfo(Context context, String preferencesKey)
{
SharedPreferences prefs = context.getSharedPreferences(preferencesKey, 0);
List<ApplicationRunInformation> allApps = new ArrayList<ApplicationRunInformation>();
Map<String, ?> componentNames = prefs.getAll();
for (String component : componentNames.keySet())
{
String data = prefs.getString(component, "");
if (data.isEmpty())
{
continue;
}
allApps.add(deserializeApplicationRunInformation(component, data));
}
return allApps;
}
public static String serializeApplicationRunInformation(ApplicationRunInformation appInfo)
{
StringBuffer sb = new StringBuffer();
sb.append(appInfo.getCount()).append(APP_RUN_INFO_SEPARATOR).append(appInfo.getLastExecution().getTime()).append(APP_RUN_INFO_SEPARATOR)
.append(appInfo.isNewApp()).append(APP_RUN_INFO_SEPARATOR).append(appInfo.isPinnedApp()).append(APP_RUN_INFO_SEPARATOR).append(appInfo.isUpdatedApp());
return sb.toString();
}
public static ApplicationRunInformation deserializeApplicationRunInformation(String component, String data)
{
String[] splits = data.split(APP_RUN_INFO_SEPARATOR);
int count;
Date lastExecution = Calendar.getInstance().getTime();
boolean isNewApp;
boolean isUpdatedApp;
boolean isPinnedApp;
try
{
count = Integer.parseInt(splits[0]);
lastExecution.setTime(Long.valueOf(splits[1]));
isNewApp = Boolean.parseBoolean(splits[2]);
isPinnedApp = Boolean.parseBoolean(splits[3]);
isUpdatedApp = Boolean.parseBoolean(splits[4]);
} catch (NumberFormatException e)
{
e.printStackTrace();
count = 0;
lastExecution = Calendar.getInstance().getTime();
isNewApp = false;
isUpdatedApp = false;
isPinnedApp = false;
} catch (ArrayIndexOutOfBoundsException e)
{
e.printStackTrace();
count = 0;
lastExecution = Calendar.getInstance().getTime();
isNewApp = false;
isUpdatedApp = false;
isPinnedApp = false;
}
ApplicationRunInformation appRunInfo = new ApplicationRunInformation(ApplicationRunInformation.deserializeComponentName(component), count);
appRunInfo.mLastExecution = lastExecution;
appRunInfo.mIsNewApp = isNewApp;
appRunInfo.mIsUpdatedApp = isUpdatedApp;
appRunInfo.mIsPinnedApp = isPinnedApp;
return appRunInfo;
}
public static enum APP_AGE
{
FREQUENT_USE, RARE_USE
}
public static long getAgeLevelInMiliseconds(Context context, APP_AGE age)
{
long result = toMilliSeconds(APP_RARE_USE_DAYS);
int frequentUseDays = getAppIdleLimitInDays(context);
switch (age)
{
case FREQUENT_USE:
result = toMilliSeconds(frequentUseDays);
break;
case RARE_USE:
result = toMilliSeconds(APP_RARE_USE_DAYS);
break;
}
return result;
}
public static int getAppIdleLimitInDays(Context context){
int frequentUseDays = context.getResources().getInteger(R.integer.app_frequent_use_one_month);
SharedPreferences sharedPreferences = context.getSharedPreferences(AppDrawerView.APP_LIFECYCLE_PREFERENCES, Activity.MODE_PRIVATE);
return sharedPreferences.getInt(AppDrawerView.APP_AGE_LIMIT_IN_DAYS, frequentUseDays);
}
public static void setAppIdleLimitInDays(Context context, int days){
SharedPreferences sharedPreferences = context.getSharedPreferences(AppDrawerView.APP_LIFECYCLE_PREFERENCES, Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(AppDrawerView.APP_AGE_LIMIT_IN_DAYS, days);
editor.commit();
}
public static long toMilliSeconds(long days)
{
return days * HOURS_IN_A_DAY * MINUTES_IN_HOUR * SECONDS_IN_MINUTE * MILLIS_IN_SECOND;
}
public void setAge(APP_AGE age)
{
mAppAge = age;
}
public APP_AGE getAge()
{
return mAppAge;
}
}