Home | History | Annotate | Download | only in compat
      1 /*
      2  * Copyright (C) 2014 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.compat;
     18 
     19 import android.content.Context;
     20 import android.content.SharedPreferences;
     21 import android.text.TextUtils;
     22 import android.util.Log;
     23 
     24 import com.android.launcher3.LauncherAppState;
     25 
     26 import org.json.JSONException;
     27 import org.json.JSONObject;
     28 import org.json.JSONStringer;
     29 import org.json.JSONTokener;
     30 
     31 import java.util.ArrayList;
     32 import java.util.HashSet;
     33 
     34 public class PackageInstallerCompatV16 extends PackageInstallerCompat {
     35 
     36     private static final String TAG = "PackageInstallerCompatV16";
     37     private static final boolean DEBUG = false;
     38 
     39     private static final String KEY_PROGRESS = "progress";
     40     private static final String KEY_STATE = "state";
     41 
     42     private static final String PREFS =
     43             "com.android.launcher3.compat.PackageInstallerCompatV16.queue";
     44 
     45     protected final SharedPreferences mPrefs;
     46 
     47     boolean mUseQueue;
     48     boolean mFinishedBind;
     49     boolean mReplayPending;
     50 
     51     PackageInstallerCompatV16(Context context) {
     52         mPrefs = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
     53     }
     54 
     55     @Override
     56     public void onPause() {
     57         mUseQueue = true;
     58         if (DEBUG) Log.d(TAG, "updates paused");
     59     }
     60 
     61     @Override
     62     public void onResume() {
     63         mUseQueue = false;
     64         if (mFinishedBind) {
     65             replayUpdates();
     66         }
     67     }
     68 
     69     @Override
     70     public void onFinishBind() {
     71         mFinishedBind = true;
     72         if (!mUseQueue) {
     73             replayUpdates();
     74         }
     75     }
     76 
     77     @Override
     78     public void onStop() { }
     79 
     80     private void replayUpdates() {
     81         if (DEBUG) Log.d(TAG, "updates resumed");
     82         LauncherAppState app = LauncherAppState.getInstanceNoCreate();
     83         if (app == null) {
     84             mReplayPending = true; // try again later
     85             if (DEBUG) Log.d(TAG, "app is null, delaying send");
     86             return;
     87         }
     88         mReplayPending = false;
     89         ArrayList<PackageInstallInfo> updates = new ArrayList<PackageInstallInfo>();
     90         for (String packageName: mPrefs.getAll().keySet()) {
     91             final String json = mPrefs.getString(packageName, null);
     92             if (!TextUtils.isEmpty(json)) {
     93                 updates.add(infoFromJson(packageName, json));
     94             }
     95         }
     96         if (!updates.isEmpty()) {
     97             sendUpdate(app, updates);
     98         }
     99     }
    100 
    101     /**
    102      * This should be called by the implementations to register a package update.
    103      */
    104     @Override
    105     public synchronized void recordPackageUpdate(String packageName, int state, int progress) {
    106         SharedPreferences.Editor editor = mPrefs.edit();
    107         PackageInstallInfo installInfo = new PackageInstallInfo(packageName);
    108         installInfo.progress = progress;
    109         installInfo.state = state;
    110         if (state == STATUS_INSTALLED) {
    111             // no longer necessary to track this package
    112             editor.remove(packageName);
    113             if (DEBUG) Log.d(TAG, "no longer tracking " + packageName);
    114         } else {
    115             editor.putString(packageName, infoToJson(installInfo));
    116             if (DEBUG)
    117                 Log.d(TAG, "saved state: " + infoToJson(installInfo)
    118                         + " for package: " + packageName);
    119 
    120         }
    121         editor.commit();
    122 
    123         if (!mUseQueue) {
    124             if (mReplayPending) {
    125                 replayUpdates();
    126             } else if (state != STATUS_INSTALLED) {
    127                 LauncherAppState app = LauncherAppState.getInstanceNoCreate();
    128                 ArrayList<PackageInstallInfo> update = new ArrayList<PackageInstallInfo>();
    129                 update.add(installInfo);
    130                 sendUpdate(app, update);
    131             }
    132         }
    133     }
    134 
    135     private void sendUpdate(LauncherAppState app, ArrayList<PackageInstallInfo> updates) {
    136         if (app == null) {
    137             mReplayPending = true; // try again later
    138             if (DEBUG) Log.d(TAG, "app is null, delaying send");
    139         } else {
    140             app.setPackageState(updates);
    141         }
    142     }
    143 
    144     private static PackageInstallInfo infoFromJson(String packageName, String json) {
    145         PackageInstallInfo info = new PackageInstallInfo(packageName);
    146         try {
    147             JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
    148             info.state = object.getInt(KEY_STATE);
    149             info.progress = object.getInt(KEY_PROGRESS);
    150         } catch (JSONException e) {
    151             Log.e(TAG, "failed to deserialize app state update", e);
    152         }
    153         return info;
    154     }
    155 
    156     private static String infoToJson(PackageInstallInfo info) {
    157         String value = null;
    158         try {
    159             JSONStringer json = new JSONStringer()
    160                     .object()
    161                     .key(KEY_STATE).value(info.state)
    162                     .key(KEY_PROGRESS).value(info.progress)
    163                     .endObject();
    164             value = json.toString();
    165         } catch (JSONException e) {
    166             Log.e(TAG, "failed to serialize app state update", e);
    167         }
    168         return value;
    169     }
    170 
    171     @Override
    172     public HashSet<String> updateAndGetActiveSessionCache() {
    173         return new HashSet<String>();
    174     }
    175 }
    176